Changeset 69eb71
- Timestamp:
- Dec 3, 2008, 2:12:05 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- f683fe
- Parents:
- 1ffa21
- Location:
- src
- Files:
-
- 6 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/boundary.cpp
r1ffa21 r69eb71 3 3 4 4 5 // =================spaeter gebrauchte6 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule mol);7 void Find_non_convex_border(Tesselation Tess, molecule mol);8 5 9 6 … … 29 26 }; 30 27 31 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 28 void BoundaryPointSet::AddLine(class BoundaryLineSet *line) 32 29 { 33 30 cout << Verbose(6) << "Adding line " << *line << " to " << *this << "." << endl; … … 40 37 }; 41 38 42 ostream & operator << (ostream &ost, BoundaryPointSet &a) 39 ostream & operator << (ostream &ost, BoundaryPointSet &a) 43 40 { 44 41 ost << "[" << a.Nr << "|" << a.node->Name << "]"; … … 73 70 { 74 71 for (int i=0;i<2;i++) { 75 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 72 cout << Verbose(5) << "Erasing Line Nr. " << Nr << " in boundary point " << *endpoints[i] << "." << endl; 76 73 endpoints[i]->lines.erase(Nr); 77 74 LineMap::iterator tester = endpoints[i]->lines.begin(); … … 85 82 }; 86 83 87 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 84 void BoundaryLineSet::AddTriangle(class BoundaryTriangleSet *triangle) 88 85 { 89 86 cout << Verbose(6) << "Add " << triangle->Nr << " to line " << *this << "." << endl; … … 92 89 }; 93 90 94 ostream & operator << (ostream &ost, BoundaryLineSet &a) 91 ostream & operator << (ostream &ost, BoundaryLineSet &a) 95 92 { 96 93 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "]"; … … 125 122 for (int j=0;j<2;j++) { // for both endpoints 126 123 OrderMap.insert ( pair <int, class BoundaryPointSet * >( line[i]->endpoints[j]->Nr, line[i]->endpoints[j]) ); 127 // and we don't care whether insertion fails 124 // and we don't care whether insertion fails 128 125 } 129 126 // set endpoints … … 161 158 // get normal vector 162 159 NormalVector.MakeNormalVector(&endpoints[0]->node->x, &endpoints[1]->node->x, &endpoints[2]->node->x); 163 160 164 161 // make it always point inward (any offset vector onto plane projected onto normal vector suffices) 165 162 if (endpoints[0]->node->x.Projection(&NormalVector) > 0) … … 167 164 }; 168 165 169 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 166 ostream & operator << (ostream &ost, BoundaryTriangleSet &a) 170 167 { 171 168 ost << "[" << a.Nr << "|" << a.endpoints[0]->node->Name << "," << a.endpoints[1]->node->Name << "," << a.endpoints[2]->node->Name << "]"; … … 213 210 LineMap LinesOnBoundary; 214 211 TriangleMap TrianglesOnBoundary; 215 212 216 213 *out << Verbose(1) << "Finding all boundary points." << endl; 217 214 Boundaries *BoundaryPoints = new Boundaries [NDIM]; // first is alpha, second is (r, nr) … … 250 247 else 251 248 angle = 0.; // otherwise it's a vector in Axis Direction and unimportant for boundary issues 252 249 253 250 //*out << "Checking sign in quadrant : " << ProjectedVector.Projection(&AngleReferenceNormalVector) << "." << endl; 254 251 if (ProjectedVector.Projection(&AngleReferenceNormalVector) > 0) { … … 268 265 Walker->x.Output(out); 269 266 *out << endl; 270 double tmp = ProjectedVector.Norm(); 267 double tmp = ProjectedVector.Norm(); 271 268 if (tmp > BoundaryTestPair.first->second.first) { 272 269 BoundaryTestPair.first->second.first = tmp; 273 BoundaryTestPair.first->second.second = Walker; 270 BoundaryTestPair.first->second.second = Walker; 274 271 *out << Verbose(2) << "Keeping new vector." << endl; 275 272 } else if (tmp == BoundaryTestPair.first->second.first) { … … 319 316 } 320 317 // check distance 321 318 322 319 // construct the vector of each side of the triangle on the projected plane (defined by normal vector AxisVector) 323 320 { … … 328 325 // SideA.Output(out); 329 326 // *out << endl; 330 327 331 328 SideB.CopyVector(&right->second.second->x); 332 329 SideB.ProjectOntoPlane(&AxisVector); … … 334 331 // SideB.Output(out); 335 332 // *out << endl; 336 333 337 334 SideC.CopyVector(&left->second.second->x); 338 335 SideC.SubtractVector(&right->second.second->x); … … 341 338 // SideC.Output(out); 342 339 // *out << endl; 343 340 344 341 SideH.CopyVector(&runner->second.second->x); 345 342 SideH.ProjectOntoPlane(&AxisVector); … … 347 344 // SideH.Output(out); 348 345 // *out << endl; 349 346 350 347 // calculate each length 351 348 double a = SideA.Norm(); … … 355 352 // calculate the angles 356 353 double alpha = SideA.Angle(&SideH); 357 double beta = SideA.Angle(&SideC); 354 double beta = SideA.Angle(&SideC); 358 355 double gamma = SideB.Angle(&SideH); 359 356 double delta = SideC.Angle(&SideH); 360 357 double MinDistance = a * sin(beta)/(sin(delta)) * (((alpha < M_PI/2.) || (gamma < M_PI/2.)) ? 1. : -1.); 361 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 358 // *out << Verbose(2) << " I calculated: a = " << a << ", h = " << h << ", beta(" << left->second.second->Name << "," << left->second.second->Name << "-" << right->second.second->Name << ") = " << beta << ", delta(" << left->second.second->Name << "," << runner->second.second->Name << ") = " << delta << ", Min = " << MinDistance << "." << endl; 362 359 //*out << Verbose(1) << "Checking CoG distance of runner " << *runner->second.second << " " << h << " against triangle's side length spanned by (" << *left->second.second << "," << *right->second.second << ") of " << MinDistance << "." << endl; 363 360 if ((fabs(h/fabs(h) - MinDistance/fabs(MinDistance)) < MYEPSILON) && (h < MinDistance)) { … … 370 367 } 371 368 } while (flag); 372 } 369 } 373 370 return BoundaryPoints; 374 371 }; … … 381 378 * \param IsAngstroem whether we have angstroem or atomic units 382 379 * \return NDIM array of the diameters 383 */ 380 */ 384 381 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem) 385 382 { … … 393 390 *out << Verbose(1) << "Using given boundary points set." << endl; 394 391 } 395 392 396 393 // determine biggest "diameter" of cluster for each axis 397 394 Boundaries::iterator Neighbour, OtherNeighbour; … … 418 415 DistanceVector.SubtractVector(&Neighbour->second.second->x); 419 416 do { // seek for neighbour pair where it flips 420 OldComponent = DistanceVector.x[Othercomponent]; 417 OldComponent = DistanceVector.x[Othercomponent]; 421 418 Neighbour++; 422 419 if (Neighbour == BoundaryPoints[axis].end()) // make it wrap around … … 431 428 OtherNeighbour = BoundaryPoints[axis].end(); 432 429 OtherNeighbour--; 433 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 430 //*out << Verbose(2) << "The pair, where the sign of OtherComponent flips, is: " << *(Neighbour->second.second) << " and " << *(OtherNeighbour->second.second) << "." << endl; 434 431 // now we have found the pair: Neighbour and OtherNeighbour 435 432 OtherVector.CopyVector(&runner->second.second->x); … … 466 463 * \param *BoundaryPoints NDIM set of boundary points on the projected plane per axis, on return if desired 467 464 * \param *mol molecule structure representing the cluster 468 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 465 * \return determined volume of the cluster in cubed config:GetIsAngstroem() 469 466 */ 470 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 467 double VolumeOfConvexEnvelope(ofstream *out, ofstream *tecplot, config *configuration, Boundaries *BoundaryPtr, molecule *mol) 471 468 { 472 469 bool IsAngstroem = configuration->GetIsAngstroem(); … … 477 474 double volume = 0.; 478 475 double PyramidVolume = 0.; 479 double G,h; 476 double G,h; 480 477 Vector x,y; 481 478 double a,b,c; 482 479 483 Find_non_convex_border(*TesselStruct, *mol);480 Find_non_convex_border(*TesselStruct, mol); 484 481 /* 485 482 // 1. calculate center of gravity 486 483 *out << endl; 487 484 Vector *CenterOfGravity = mol->DetermineCenterOfGravity(out); 488 485 489 486 // 2. translate all points into CoG 490 487 *out << Verbose(1) << "Translating system to Center of Gravity." << endl; … … 494 491 Walker->x.Translate(CenterOfGravity); 495 492 } 496 493 497 494 // 3. Find all points on the boundary 498 495 if (BoundaryPoints == NULL) { … … 502 499 *out << Verbose(1) << "Using given boundary points set." << endl; 503 500 } 504 501 505 502 // 4. fill the boundary point list 506 503 for (int axis=0;axis<NDIM;axis++) … … 518 515 // } 519 516 // *out << endl; 520 517 521 518 // 5a. guess starting triangle 522 519 TesselStruct->GuessStartingTriangle(out); 523 520 524 521 // 5b. go through all lines, that are not yet part of two triangles (only of one so far) 525 522 TesselStruct->TesselateOnBoundary(out, configuration, mol); … … 545 542 PyramidVolume = (1./3.) * G * h; // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak) 546 543 *out << Verbose(2) << "Area of triangle is " << G << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^2, height is " << h << " and the volume is " << PyramidVolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 547 volume += PyramidVolume; 544 volume += PyramidVolume; 548 545 } 549 546 *out << Verbose(0) << "RESULT: The summed volume is " << setprecision(10) << volume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; … … 572 569 for (int i=0;i<mol->AtomCount;i++) 573 570 LookupList[i] = -1; 574 571 575 572 // print atom coordinates 576 573 *out << Verbose(2) << "The following triangles were created:"; … … 586 583 for (TriangleMap::iterator runner = TesselStruct->TrianglesOnBoundary.begin(); runner != TesselStruct->TrianglesOnBoundary.end(); runner++) { 587 584 *out << " " << runner->second->endpoints[0]->node->Name << "<->" << runner->second->endpoints[1]->node->Name << "<->" << runner->second->endpoints[2]->node->Name; 588 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 585 *tecplot << LookupList[runner->second->endpoints[0]->node->nr] << " " << LookupList[runner->second->endpoints[1]->node->nr] << " " << LookupList[runner->second->endpoints[2]->node->nr] << endl; 589 586 } 590 587 delete[](LookupList); … … 595 592 if (BoundaryFreeFlag) 596 593 delete[](BoundaryPoints); 597 594 598 595 return volume; 599 596 }; … … 612 609 // transform to PAS 613 610 mol->PrincipalAxisSystem(out, true); 614 611 615 612 // some preparations beforehand 616 613 bool IsAngstroem = configuration->GetIsAngstroem(); … … 619 616 if (ClusterVolume == 0) 620 617 clustervolume = VolumeOfConvexEnvelope(out, NULL, configuration, BoundaryPoints, mol); 621 else 618 else 622 619 clustervolume = ClusterVolume; 623 620 double *GreatestDiameter = GetDiametersOfCluster(out, BoundaryPoints, mol, IsAngstroem); … … 636 633 } 637 634 *out << Verbose(0) << "RESULT: The summed mass is " << setprecision(10) << totalmass << " atomicmassunit." << endl; 638 635 639 636 *out << Verbose(0) << "RESULT: The average density is " << setprecision(10) << totalmass/clustervolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 640 637 641 638 // solve cubic polynomial 642 639 *out << Verbose(1) << "Solving equidistant suspension in water problem ..." << endl; … … 647 644 cellvolume = (TotalNoClusters*totalmass/SOLVENTDENSITY_a0 - (totalmass/clustervolume))/(celldensity-1); 648 645 *out << Verbose(1) << "Cellvolume needed for a density of " << celldensity << " g/cm^3 is " << cellvolume << " " << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; 649 646 650 647 double minimumvolume = TotalNoClusters*(GreatestDiameter[0]*GreatestDiameter[1]*GreatestDiameter[2]); 651 648 *out << Verbose(1) << "Minimum volume of the convex envelope contained in a rectangular box is " << minimumvolume << " atomicmassunit/" << (IsAngstroem ? "angstrom" : "atomiclength") << "^3." << endl; … … 658 655 } else { 659 656 BoxLengths.x[0] = (repetition[0]*GreatestDiameter[0] + repetition[1]*GreatestDiameter[1] + repetition[2]*GreatestDiameter[2]); 660 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 661 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 657 BoxLengths.x[1] = (repetition[0]*repetition[1]*GreatestDiameter[0]*GreatestDiameter[1] 658 + repetition[0]*repetition[2]*GreatestDiameter[0]*GreatestDiameter[2] 662 659 + repetition[1]*repetition[2]*GreatestDiameter[1]*GreatestDiameter[2]); 663 660 BoxLengths.x[2] = minimumvolume - cellvolume; … … 669 666 x0 = x2; // sorted in ascending order 670 667 } 671 668 672 669 cellvolume = 1; 673 670 for(int i=0;i<NDIM;i++) { … … 675 672 cellvolume *= BoxLengths.x[i]; 676 673 } 677 674 678 675 // set new box dimensions 679 676 *out << Verbose(0) << "Translating to box with these boundaries." << endl; … … 692 689 Tesselation::Tesselation() 693 690 { 694 PointsOnBoundaryCount = 0; 695 LinesOnBoundaryCount = 0; 691 PointsOnBoundaryCount = 0; 692 LinesOnBoundaryCount = 0; 696 693 TrianglesOnBoundaryCount = 0; 697 694 }; … … 711 708 * \param *out output stream for debugging 712 709 * \param PointsOnBoundary set of boundary points defining the convex envelope of the cluster 713 */ 710 */ 714 711 void Tesselation::GuessStartingTriangle(ofstream *out) 715 712 { … … 722 719 A = PointsOnBoundary.begin(); // the first may be chosen arbitrarily 723 720 724 // with A chosen, take each pair B,C and sort 721 // with A chosen, take each pair B,C and sort 725 722 if (A != PointsOnBoundary.end()) { 726 723 B = A; … … 746 743 // } 747 744 // *out << endl; 748 745 749 746 // 4b2. pick three baselines forming a triangle 750 747 // 1. we take from the smallest sum of squared distance as the base line BC (with peak A) onward as the triangle candidate … … 758 755 PlaneVector.Output(out); 759 756 *out << endl; 760 // 4. loop over all points 757 // 4. loop over all points 761 758 double sign = 0.; 762 759 PointMap::iterator checker = PointsOnBoundary.begin(); … … 785 782 tmp = checker->second->node->x.Distance(&A->second->node->x); 786 783 int innerpoint = 0; 787 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 784 if ((tmp < A->second->node->x.Distance(&baseline->second.first->second->node->x)) 788 785 && (tmp < A->second->node->x.Distance(&baseline->second.second->second->node->x))) 789 786 innerpoint++; 790 787 tmp = checker->second->node->x.Distance(&baseline->second.first->second->node->x); 791 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 788 if ((tmp < baseline->second.first->second->node->x.Distance(&A->second->node->x)) 792 789 && (tmp < baseline->second.first->second->node->x.Distance(&baseline->second.second->second->node->x))) 793 790 innerpoint++; 794 791 tmp = checker->second->node->x.Distance(&baseline->second.second->second->node->x); 795 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 792 if ((tmp < baseline->second.second->second->node->x.Distance(&baseline->second.first->second->node->x)) 796 793 && (tmp < baseline->second.second->second->node->x.Distance(&A->second->node->x))) 797 794 innerpoint++; … … 815 812 BPS[0] = baseline->second.first->second; 816 813 BPS[1] = A->second; 817 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 818 814 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 815 819 816 // 4b3. insert created triangle 820 817 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); … … 825 822 LinesOnBoundaryCount++; 826 823 } 827 824 828 825 *out << Verbose(1) << "Starting triangle is " << *BTS << "." << endl; 829 826 } else { … … 857 854 do { 858 855 flag = false; 859 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 856 for (LineMap::iterator baseline = LinesOnBoundary.begin(); baseline != LinesOnBoundary.end(); baseline++) 860 857 if (baseline->second->TrianglesCount == 1) { 861 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 858 *out << Verbose(2) << "Current baseline is between " << *(baseline->second) << "." << endl; 862 859 // 5a. go through each boundary point if not _both_ edges between either endpoint of the current line and this point exist (and belong to 2 triangles) 863 860 SmallestAngle = M_PI; … … 888 885 TempVector.CopyVector(&CenterVector); 889 886 TempVector.SubtractVector(&baseline->second->endpoints[0]->node->x); // TempVector is vector on triangle plane pointing from one baseline egde towards center! 890 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 887 //*out << Verbose(2) << "Projection of propagation onto temp: " << PropagationVector.Projection(&TempVector) << "." << endl; 891 888 if (PropagationVector.Projection(&TempVector) > 0) // make sure normal propagation vector points outward from baseline 892 889 PropagationVector.Scale(-1.); … … 895 892 *out << endl; 896 893 winner = PointsOnBoundary.end(); 897 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 894 for (PointMap::iterator target = PointsOnBoundary.begin(); target != PointsOnBoundary.end(); target++) 898 895 if ((target->second != baseline->second->endpoints[0]) && (target->second != baseline->second->endpoints[1])) { // don't take the same endpoints 899 896 *out << Verbose(3) << "Target point is " << *(target->second) << ":"; 900 897 bool continueflag = true; 901 898 902 899 VirtualNormalVector.CopyVector(&baseline->second->endpoints[0]->node->x); 903 900 VirtualNormalVector.AddVector(&baseline->second->endpoints[0]->node->x); … … 935 932 // check whether the envisaged triangle does not already exist (if both lines exist and have same endpoint) 936 933 continueflag = continueflag && (!( 937 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 934 ((LineChecker[0] != baseline->second->endpoints[0]->lines.end()) && (LineChecker[1] != baseline->second->endpoints[1]->lines.end()) 938 935 && (GetCommonEndpoint(LineChecker[0]->second, LineChecker[1]->second) == peak)) 939 936 )); … … 990 987 *out << Verbose(1) << "I could not determine a winner for this baseline " << *(baseline->second) << "." << endl; 991 988 } 992 989 993 990 // 5d. If the set of lines is not yet empty, go to 5. and continue 994 991 } else 995 992 *out << Verbose(2) << "Baseline candidate " << *(baseline->second) << " has a triangle count of " << baseline->second->TrianglesCount << "." << endl; 996 993 } while (flag); 997 994 998 995 }; 999 996 … … 1021 1018 //==================================================================================================================== 1022 1019 1023 1024 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule mol) 1025 { 1026 /* d2 ist der Normalenvektor auf dem Dreieck, 1027 * d1 ist der Vektor, der normal auf der Kante und d2 steht. 1020 /*! 1021 * This recursive function finds a third point, to form a triangle with two given ones. 1022 * Two atoms are fixed, a candidate is supplied, additionally two vectors for direction distinction, a Storage area to \ 1023 * supply results to the calling function, the radius of the sphere which the triangle shall support and the molecule \ 1024 * upon which we operate. 1025 * If the candidate is more fitting to support the sphere than the already stored atom is, then we write its id, its general \ 1026 * direction and angle into Storage. 1027 * We the determine the recursive level we have reached and if this is not on the threshold yet, call this function again, \ 1028 * with all neighbours of the candidate. 1029 */ 1030 void Find_next_suitable_point(atom* a, atom* b, atom* Candidate, int n, Vector *Chord, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule* mol) 1031 { 1032 /* d2 is normal vector on the triangle 1033 * d1 is normal on the triangle line, from which we come, as well as on d2. 1028 1034 */ 1029 Vector dif_a; 1030 Vector dif_b; 1031 Vector Chord; 1032 Vector AngleCheck; 1033 atom *Walker; 1034 1035 dif_a.CopyVector(&a.x); 1036 dif_a.SubtractVector(&Candidate.x); 1037 dif_b.CopyVector(&b.x); 1038 dif_b.SubtractVector(&Candidate.x); 1039 Chord.CopyVector(&a.x); 1040 Chord.SubtractVector(&b.x); 1035 Vector dif_a; //Vector from a to candidate 1036 Vector dif_b; //Vector from b to candidate 1037 Vector AngleCheck; // Projection of a difference vector on plane orthogonal on triangle side. 1038 atom *Walker; // variable atom point 1039 1040 dif_a.CopyVector(&(a->x)); 1041 dif_a.SubtractVector(&(Candidate->x)); 1042 dif_b.CopyVector(&(b->x)); 1043 dif_b.SubtractVector(&(Candidate->x)); 1041 1044 AngleCheck.CopyVector(&dif_a); 1042 AngleCheck.ProjectOntoPlane(&Chord); 1043 1044 //Storage eintrag fuer aktuelles Atom 1045 if (Chord.Norm()/(2*sin(dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find of Ball will touch atom 1045 AngleCheck.ProjectOntoPlane(Chord); 1046 1047 if (Chord->Norm()/(2*sin(dif_a.Angle(&dif_b)))<RADIUS) //Using Formula for relation of chord length with inner angle to find of Ball will touch atom 1046 1048 { 1047 1049 1048 1050 if (dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1))>Storage[1]) //This will give absolute preference to those in "right-hand" quadrants 1049 1051 { 1050 Storage[0]=(double)Candidate.nr;1051 Storage[1]=1;1052 Storage[2]=AngleCheck.Angle(d2);1052 Storage[0]=(double)Candidate->nr; 1053 Storage[1]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1054 Storage[2]=AngleCheck.Angle(d2); 1053 1055 } 1054 1056 else … … 1058 1060 //Depending on quadrant we prefer higher or lower atom with respect to Triangle normal first. 1059 1061 { 1060 Storage[0]=(double)Candidate .nr;1062 Storage[0]=(double)Candidate->nr; 1061 1063 Storage[1]=dif_a.ScalarProduct(d1)/fabs(dif_a.ScalarProduct(d1)); 1062 1064 Storage[2]=AngleCheck.Angle(d2); … … 1065 1067 } 1066 1068 1067 if (n<5) 1068 { 1069 for(int i=0; i<mol .NumberOfBondsPerAtom[Candidate.nr];i++)1069 if (n<5) // Five is the recursion level threshold. 1070 { 1071 for(int i=0; i<mol->NumberOfBondsPerAtom[Candidate->nr];i++) // go through all bond 1070 1072 { 1071 while (Candidate.nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr)) 1072 { 1073 Walker= mol->start; // go through all atoms 1074 1075 while (Walker->nr != (mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr ==Candidate->nr ? mol->ListOfBondsPerAtom[Candidate->nr][i]->rightatom->nr : mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr)) 1076 { // until atom found which belongs to bond 1073 1077 Walker = Walker->next; 1074 1078 } 1075 1079 1076 Find_next_suitable_point(a, b, *Walker, n+1, d1, d2, Storage, RADIUS, mol); 1080 1081 Find_next_suitable_point(a, b, Walker, n+1, Chord, d1, d2, Storage, RADIUS, mol); //call function again 1077 1082 } 1078 1083 } 1079 1084 }; 1080 1085 1081 1082 void Tesselation::Find_next_suitable_triangle(molecule *mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS) 1083 { 1084 Vector CenterOfLine = Line.endpoints[0]->node->x; 1086 /*! 1087 * this function fins a triangle to a line, adjacent to an existing one. 1088 */ 1089 void Tesselation::Find_next_suitable_triangle(molecule* mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS) 1090 { 1091 printf("Looking for next suitable triangle \n"); 1085 1092 Vector direction1; 1086 Vector direction2;1087 1093 Vector helper; 1094 Vector Chord; 1088 1095 atom* Walker; 1089 1096 1090 double Storage[3]; 1097 double *Storage; 1098 Storage = new double[3]; 1091 1099 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1092 1100 Storage[1]=-1.; // This direction is either +1 or -1 one, so any result will take precedence over initial values 1093 1101 Storage[2]=-10.; // This is also lower then any value produced by an eligible atom, which are all positive 1094 1102 1095 1103 1096 1104 helper.CopyVector(&(Line.endpoints[0]->node->x)); 1097 1105 for (int i =0; i<3; i++) … … 1114 1122 } 1115 1123 1116 Find_next_suitable_point(*Line.endpoints[0]->node, *Line.endpoints[1]->node, *Line.endpoints[0]->node, 0, &direction1, T.NormalVector, Storage, RADIUS, *mol); 1117 1124 Chord.CopyVector(&(Line.endpoints[0]->node->x)); // bring into calling function 1125 Chord.SubtractVector(&(Line.endpoints[1]->node->x)); 1126 1127 printf("Looking for third point candidates for triangle \n"); 1128 Find_next_suitable_point(Line.endpoints[0]->node, Line.endpoints[1]->node, Line.endpoints[0]->node, 0, &Chord, &direction1, T.NormalVector, Storage, RADIUS, mol); 1129 1118 1130 // Konstruiere nun neues Dreieck am Ende der Liste der Dreiecke 1119 1131 // Next Triangle is Line, atom with number in Storage[0] … … 1141 1153 for(int i=0;i<NDIM;i++) // sind Linien bereits vorhanden ??? 1142 1154 { 1143 if (LinesOnBoundary.find(BTS->lines[i]) == LinesOnBoundary.end) 1155 1156 1157 if ( (LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]))).second); 1144 1158 { 1145 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); 1146 LinesOnBoundaryCount++; 1159 LinesOnBoundaryCount++; 1147 1160 } 1148 1161 } … … 1154 1167 BTS->NormalVector->Scale(-1); 1155 1168 } 1156 1157 }; 1158 1159 1160 void Find_second_point_for_Tesselation(atom a, atom Candidate, int n, Vector Oben, double* Storage, molecule mol) 1161 { 1169 1170 }; 1171 1172 1173 void Find_second_point_for_Tesselation(atom* a, atom* Candidate, int n, Vector Oben, double Storage[3], molecule* mol) 1174 { 1175 printf("Looking for second point of starting triangle \n"); 1162 1176 int i; 1163 1177 Vector *AngleCheck; 1164 1178 atom* Walker; 1165 1179 1166 AngleCheck->CopyVector(&Candidate.x); 1167 AngleCheck->SubtractVector(&a.x); 1168 if (AngleCheck->ScalarProduct(&Oben) < Storage[1]) 1169 { 1170 Storage[0]=(double)(Candidate.nr); 1171 Storage[1]=AngleCheck->ScalarProduct(&Oben); 1180 AngleCheck->CopyVector(&(Candidate->x)); 1181 AngleCheck->SubtractVector(&(a->x)); 1182 if (AngleCheck->Angle(&Oben) < Storage[1]) 1183 { 1184 //printf("Old values of Storage: %lf %lf \n", Storage[0], Storage[1]); 1185 Storage[0]=(double)(Candidate->nr); 1186 Storage[1]=AngleCheck->Angle(&Oben); 1187 //printf("Changing something in Storage: %lf %lf. \n", Storage[0], Storage[1]); 1172 1188 }; 1173 1189 printf("%d \n", n); 1174 1190 if (n<5) 1175 1191 { 1176 for (i = 0; i< mol .NumberOfBondsPerAtom[Candidate.nr]; i++)1192 for (i = 0; i< mol->NumberOfBondsPerAtom[Candidate->nr]; i++) 1177 1193 { 1178 Walker = mol .start;1179 while (Candidate .nr != (mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr ==Candidate.nr ? mol.ListOfBondsPerAtom[Candidate.nr][i]->leftatom->nr : mol.ListOfBondsPerAtom[Candidate.nr][i]->rightatom->nr))1194 Walker = mol->start; 1195 while (Candidate->nr != (mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr ==Candidate->nr ? mol->ListOfBondsPerAtom[Candidate->nr][i]->leftatom->nr : mol->ListOfBondsPerAtom[Candidate->nr][i]->rightatom->nr)) 1180 1196 { 1181 1197 Walker = Walker->next; 1182 1198 }; 1183 1184 Find_second_point_for_Tesselation(a, *Walker, n+1, Oben, Storage, mol);1199 1200 Find_second_point_for_Tesselation(a, Walker, n+1, Oben, Storage, mol); 1185 1201 }; 1186 1202 }; 1187 1188 1189 }; 1190 1191 1192 void Tesselation::Find_starting_triangle(molecule mol, const double RADIUS) 1193 { 1203 1204 1205 }; 1206 1207 1208 void Tesselation::Find_starting_triangle(molecule* mol, const double RADIUS) 1209 { 1210 printf("Looking for starting triangle \n"); 1194 1211 int i=0; 1195 atom Walker;1196 atom Walker2;1197 atom Walker3;1212 atom* Walker; 1213 atom* Walker2; 1214 atom* Walker3; 1198 1215 int max_index[3]; 1199 1216 double max_coordinate[3]; 1200 1217 Vector Oben; 1201 1218 Vector helper; 1219 Vector Chord; 1202 1220 1203 1221 Oben.Zero(); … … 1209 1227 max_coordinate[i] =-1; 1210 1228 } 1211 1212 Walker = *mol.start; 1213 while (Walker.next != NULL) 1214 { 1229 printf("Molecule mol is there and has %d Atoms \n", mol->AtomCount); 1230 Walker = mol->start; 1231 while (Walker->next != mol->end) 1232 { 1233 Walker = Walker->next; 1215 1234 for (i=0; i<3; i++) 1216 1217 if (Walker .x.x[i]>max_coordinate[i])1235 { 1236 if (Walker->x.x[i] > max_coordinate[i]) 1218 1237 { 1219 max_coordinate[i]=Walker .x.x[i];1220 max_index[i]=Walker .nr;1238 max_coordinate[i]=Walker->x.x[i]; 1239 max_index[i]=Walker->nr; 1221 1240 } 1222 } 1223 } 1224 1241 } 1242 } 1243 1244 printf("Found starting atom \n"); 1225 1245 //Koennen dies fuer alle Richtungen, legen hier erstmal Richtung auf k=0 1226 const int k=0; 1227 1228 Oben.x[k]=1; 1229 Walker = *mol.start; 1230 while (Walker.nr != max_index[k]) 1231 { 1232 Walker = *Walker.next; 1233 } 1234 1246 const int k=2; 1247 1248 Oben.x[k]=1.; 1249 Walker = mol->start; 1250 Walker = Walker->next; 1251 while (Walker->nr != max_index[k]) 1252 { 1253 Walker = Walker->next; 1254 } 1255 printf("%d \n", Walker->nr); 1235 1256 double Storage[3]; 1236 1257 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1237 Storage[1]=-2.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 1238 Storage[2]=-10.; // This will be an angle looking for the third point. 1239 1240 1241 for (i=0; i< mol.NumberOfBondsPerAtom[Walker.nr]; i++) 1242 { 1243 Walker2 = *mol.start; 1244 while (Walker2.nr != (mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom->nr : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr) ) 1258 Storage[1]=999999.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 1259 Storage[2]=999999.; // This will be an angle looking for the third point. 1260 printf("%d \n", mol->NumberOfBondsPerAtom[Walker->nr]); 1261 1262 for (i=1; i< (mol->NumberOfBondsPerAtom[Walker->nr]); i++) 1263 { 1264 Walker2 = mol->start; 1265 Walker2 = Walker2->next; 1266 while (Walker2->nr != (mol->ListOfBondsPerAtom[Walker->nr][i]->leftatom->nr == Walker->nr ? mol->ListOfBondsPerAtom[Walker->nr][i]->rightatom->nr : mol->ListOfBondsPerAtom[Walker->nr][i]->leftatom->nr) ) 1245 1267 { 1246 Walker2 = *Walker2.next;1268 Walker2 = Walker2->next; 1247 1269 } 1248 1270 … … 1250 1272 } 1251 1273 1252 Walker2 = *mol.start;1253 1254 while (Walker2 .nr != int(Storage[0]))1255 { 1256 Walker = *Walker.next;1257 } 1258 1259 helper.CopyVector(& Walker.x);1260 helper.SubtractVector(& Walker2.x);1274 Walker2 = mol->start; 1275 1276 while (Walker2->nr != int(Storage[0])) 1277 { 1278 Walker2 = Walker2->next; 1279 } 1280 1281 helper.CopyVector(&(Walker->x)); 1282 helper.SubtractVector(&(Walker2->x)); 1261 1283 Oben.ProjectOntoPlane(&helper); 1262 1284 helper.VectorProduct(&Oben); 1263 1264 Find_next_suitable_point(Walker, Walker2, *(mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom->nr == Walker.nr ? mol.ListOfBondsPerAtom[Walker.nr][i]->rightatom : mol.ListOfBondsPerAtom[Walker.nr][i]->leftatom), 0, &helper, &Oben, Storage, RADIUS, mol); 1265 Walker3 = *mol.start; 1266 while (Walker3.nr != int(Storage[0])) 1267 { 1268 Walker3 = *Walker3.next; 1285 Storage[0]=-1.; // Id must be positive, we see should nothing be done 1286 Storage[1]=-2.; // This will contain the angle, which will be always positive (when looking for second point), when looking for third point this will be the quadrant. 1287 Storage[2]= -10.; // This will be an angle looking for the third point. 1288 1289 Chord.CopyVector(&(Walker->x)); // bring into calling function 1290 Chord.SubtractVector(&(Walker2->x)); 1291 1292 printf("Looking for third point candidates \n"); 1293 Find_next_suitable_point(Walker, Walker2, (mol->ListOfBondsPerAtom[Walker->nr][0]->leftatom->nr == Walker->nr ? mol->ListOfBondsPerAtom[Walker->nr][0]->rightatom : mol->ListOfBondsPerAtom[Walker->nr][0]->leftatom), 0, &Chord, &helper, &Oben, Storage, RADIUS, mol); 1294 Walker3 = mol->start; 1295 while (Walker3->nr != int(Storage[0])) 1296 { 1297 Walker3 = Walker3->next; 1269 1298 } 1270 1299 1271 1300 //Starting Triangle is Walker, Walker2, index Storage[0] 1272 1301 1273 AddPoint( &Walker);1274 AddPoint( &Walker2);1275 AddPoint( &Walker3);1276 1277 BPS[0] = new class BoundaryPointSet( &Walker);1278 BPS[1] = new class BoundaryPointSet( &Walker2);1302 AddPoint(Walker); 1303 AddPoint(Walker2); 1304 AddPoint(Walker3); 1305 1306 BPS[0] = new class BoundaryPointSet(Walker); 1307 BPS[1] = new class BoundaryPointSet(Walker2); 1279 1308 BLS[0] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1280 BPS[0] = new class BoundaryPointSet( &Walker);1281 BPS[1] = new class BoundaryPointSet( &Walker3);1309 BPS[0] = new class BoundaryPointSet(Walker); 1310 BPS[1] = new class BoundaryPointSet(Walker3); 1282 1311 BLS[1] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1283 BPS[0] = new class BoundaryPointSet( &Walker);1284 BPS[1] = new class BoundaryPointSet( &Walker2);1285 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1312 BPS[0] = new class BoundaryPointSet(Walker); 1313 BPS[1] = new class BoundaryPointSet(Walker2); 1314 BLS[2] = new class BoundaryLineSet(BPS , LinesOnBoundaryCount); 1286 1315 1287 1316 BTS = new class BoundaryTriangleSet(BLS, TrianglesOnBoundaryCount); … … 1289 1318 TrianglesOnBoundaryCount++; 1290 1319 1291 for(int i=0;i<NDIM;i++) 1320 for(int i=0;i<NDIM;i++) 1292 1321 { 1293 1322 LinesOnBoundary.insert( LinePair(LinesOnBoundaryCount, BTS->lines[i]) ); … … 1304 1333 1305 1334 1306 void Find_non_convex_border(Tesselation* Tess, molecule mol) 1307 { 1335 void Find_non_convex_border(Tesselation Tess, molecule* mol) 1336 { 1337 printf("Entering finding of non convex hull. \n"); 1308 1338 const double RADIUS =6; 1309 Tess ->Find_starting_triangle(mol, RADIUS);1310 1311 for (LineMap::iterator baseline = Tess ->LinesOnBoundary.begin(); baseline != Tess->LinesOnBoundary.end(); baseline++)1312 if (baseline->second->TrianglesCount == 1) 1339 Tess.Find_starting_triangle(mol, RADIUS); 1340 1341 for (LineMap::iterator baseline = Tess.LinesOnBoundary.begin(); baseline != Tess.LinesOnBoundary.end(); baseline++) 1342 if (baseline->second->TrianglesCount == 1) 1313 1343 { 1314 Tess->Find_next_suitable_triangle(&mol, baseline->second, baseline->second->triangles.begin()->second, RADIUS); //the line is there, so there is a triangle, but only one. 1315 1344 Tess.Find_next_suitable_triangle(mol, *(baseline->second), *(baseline->second->triangles.begin()->second), RADIUS); //the line is there, so there is a triangle, but only one. 1316 1345 } 1317 1346 else -
src/boundary.hpp
r1ffa21 r69eb71 82 82 void GuessStartingTriangle(ofstream *out); 83 83 void AddPoint(atom * Walker); 84 void Find_starting_triangle(molecule mol, const double RADIUS);84 void Find_starting_triangle(molecule* mol, const double RADIUS); 85 85 void Find_next_suitable_triangle(molecule* mol, BoundaryLineSet Line, BoundaryTriangleSet T, const double& RADIUS); 86 86 … … 105 105 double * GetDiametersOfCluster(ofstream *out, Boundaries *BoundaryPtr, molecule *mol, bool IsAngstroem); 106 106 void PrepareClustersinWater(ofstream *out, config *configuration, molecule *mol, double ClusterVolume, double celldensity); 107 void Find_next_suitable_point(atom a, atom b, atom Candidate, int n, Vector *d1, Vector *d2, double *Storage, const double RADIUS, molecule *mol); 108 void Find_non_convex_border(Tesselation Tess, molecule* mol); 107 109 108 110 -
src/molecules.cpp
r1ffa21 r69eb71 1 1 /** \file molecules.cpp 2 * 2 * 3 3 * Functions for the class molecule. 4 * 4 * 5 5 */ 6 6 … … 25 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 26 } 27 27 28 28 return sum; 29 29 }; … … 34 34 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 35 35 */ 36 molecule::molecule(periodentafel *teil) 37 { 36 molecule::molecule(periodentafel *teil) 37 { 38 38 // init atom chain list 39 start = new atom; 39 start = new atom; 40 40 end = new atom; 41 start->father = NULL; 41 start->father = NULL; 42 42 end->father = NULL; 43 43 link(start,end); … … 46 46 last = new bond(start, end, 1, -1); 47 47 link(first,last); 48 // other stuff 48 // other stuff 49 49 MDSteps = 0; 50 last_atom = 0; 50 last_atom = 0; 51 51 elemente = teil; 52 52 AtomCount = 0; … … 67 67 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 68 68 */ 69 molecule::~molecule() 69 molecule::~molecule() 70 70 { 71 71 if (ListOfBondsPerAtom != NULL) … … 78 78 delete(last); 79 79 delete(end); 80 delete(start); 80 delete(start); 81 81 }; 82 82 83 83 /** Adds given atom \a *pointer from molecule list. 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 85 85 * \param *pointer allocated and set atom 86 86 * \return true - succeeded, false - atom not found in list 87 87 */ 88 88 bool molecule::AddAtom(atom *pointer) 89 { 89 { 90 90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 91 pointer->sort = &pointer->nr; 92 92 pointer->nr = last_atom++; // increase number within molecule 93 93 AtomCount++; … … 106 106 return add(pointer, end); 107 107 } else 108 return false; 108 return false; 109 109 }; 110 110 … … 115 115 */ 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 { 117 { 118 118 if (pointer != NULL) { 119 119 atom *walker = new atom(); … … 122 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 124 walker->sort = &walker->nr; 125 125 walker->nr = last_atom++; // increase number within molecule 126 126 walker->father = pointer; //->GetTrueFather(); … … 133 133 return walker; 134 134 } else 135 return NULL; 135 return NULL; 136 136 }; 137 137 … … 156 156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 157 157 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 159 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 161 161 * \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$. 162 * 162 * 163 163 * \param *out output stream for debugging 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 166 166 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule … … 191 191 InBondvector.SubtractVector(&TopOrigin->x); 192 192 bondlength = InBondvector.Norm(); 193 193 194 194 // is greater than typical bond distance? Then we have to correct periodically 195 195 // the problem is not the H being out of the box, but InBondvector have the wrong direction 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 198 198 // *out << Verbose(4) << "InBondvector is: "; 199 199 // InBondvector.Output(out); … … 215 215 // *out << endl; 216 216 } // periodic correction finished 217 217 218 218 InBondvector.Normalize(); 219 219 // get typical bond length and store as scale factor for later … … 222 222 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 223 return false; 224 BondRescale = bondlength; 224 BondRescale = bondlength; 225 225 } else { 226 226 if (!IsAngstroem) … … 273 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 274 274 // *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; 275 275 276 276 // determine the plane of these two with the *origin 277 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 286 286 Orthovector1.Normalize(); 287 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 288 289 289 // create the two Hydrogens ... 290 290 FirstOtherAtom = new atom(); … … 318 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 319 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 321 SecondOtherAtom->x.Scale(&BondRescale); 322 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 323 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 326 } … … 365 365 // *out << endl; 366 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 368 368 // Orthovector2.Output(out); 369 369 // *out << endl; 370 370 371 371 // create correct coordination for the three atoms 372 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 380 380 factors[0] = d; 381 381 factors[1] = f; 382 factors[2] = 0.; 382 factors[2] = 0.; 383 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 384 factors[1] = -0.5*f; 385 factors[2] = g; 385 factors[2] = g; 386 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 387 factors[2] = -g; 388 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 389 … … 437 437 */ 438 438 bool molecule::AddXYZFile(string filename) 439 { 439 { 440 440 istringstream *input = NULL; 441 441 int NumberOfAtoms = 0; // atom number in xyz read … … 446 446 string line; // currently parsed line 447 447 double x[3]; // atom coordinates 448 448 449 449 xyzfile.open(filename.c_str()); 450 450 if (!xyzfile) … … 454 454 input = new istringstream(line); 455 455 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 457 getline(xyzfile,line,'\n'); // Read comment 458 458 cout << Verbose(1) << "Comment: " << line << endl; 459 459 460 460 if (MDSteps == 0) // no atoms yet present 461 461 MDSteps++; … … 491 491 xyzfile.close(); 492 492 delete(input); 493 return true; 493 return true; 494 494 }; 495 495 … … 503 503 atom *LeftAtom = NULL, *RightAtom = NULL; 504 504 atom *Walker = NULL; 505 505 506 506 // copy all atoms 507 507 Walker = start; … … 510 510 CurrentAtom = copy->AddCopyAtom(Walker); 511 511 } 512 512 513 513 // copy all bonds 514 514 bond *Binder = first; … … 534 534 copy->NoCyclicBonds++; 535 535 NewBond->Type = Binder->Type; 536 } 536 } 537 537 // correct fathers 538 538 Walker = copy->start; … … 551 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 552 } 553 553 554 554 return copy; 555 555 }; … … 576 576 577 577 /** Remove bond from bond chain list. 578 * \todo Function not implemented yet 578 * \todo Function not implemented yet 579 579 * \param *pointer bond pointer 580 580 * \return true - bound found and removed, false - bond not found/removed … … 588 588 589 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 590 * \todo Function not implemented yet 590 * \todo Function not implemented yet 591 591 * \param *BondPartner atom to be removed 592 592 * \return true - bounds found and removed, false - bonds not found/removed … … 621 621 Vector *min = new Vector; 622 622 Vector *max = new Vector; 623 623 624 624 // gather min and max for each axis 625 625 ptr = start->next; // start at first in list … … 667 667 { 668 668 Vector *min = new Vector; 669 669 670 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 671 atom *ptr = start->next; // start at first in list … … 683 683 } 684 684 } 685 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 686 686 // max->Output(out); 687 687 // *out << ", Minimum is "; … … 691 691 max->AddVector(min); 692 692 Translate(min); 693 } 693 } 694 694 delete(min); 695 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 }; 696 }; 697 697 698 698 /** Centers the center of the atoms at (0,0,0). … … 704 704 int Num = 0; 705 705 atom *ptr = start->next; // start at first in list 706 706 707 707 for(int i=NDIM;i--;) // zero center vector 708 708 center->x[i] = 0.; 709 709 710 710 if (ptr != end) { //list not empty? 711 711 while (ptr->next != end) { // continue with second if present 712 712 ptr = ptr->next; 713 713 Num++; 714 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 715 715 } 716 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 717 Translate(center); 718 718 } 719 }; 719 }; 720 720 721 721 /** Returns vector pointing to center of gravity. … … 729 729 Vector tmp; 730 730 double Num = 0; 731 731 732 732 a->Zero(); 733 733 … … 737 737 Num += 1.; 738 738 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 739 a->AddVector(&tmp); 740 740 } 741 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 757 757 Vector tmp; 758 758 double Num = 0; 759 759 760 760 a->Zero(); 761 761 … … 766 766 tmp.CopyVector(&ptr->x); 767 767 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 768 a->AddVector(&tmp); 769 769 } 770 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 789 789 Translate(center); 790 790 } 791 }; 791 }; 792 792 793 793 /** Scales all atoms by \a *factor. … … 803 803 Trajectories[ptr].R.at(j).Scale(factor); 804 804 ptr->x.Scale(factor); 805 } 806 }; 807 808 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 809 809 * \param trans[] translation vector. 810 810 */ … … 818 818 Trajectories[ptr].R.at(j).Translate(trans); 819 819 ptr->x.Translate(trans); 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 824 824 * \param n[] normal vector of mirror plane. 825 825 */ … … 833 833 Trajectories[ptr].R.at(j).Mirror(n); 834 834 ptr->x.Mirror(n); 835 } 835 } 836 836 }; 837 837 … … 847 847 bool flag; 848 848 Vector Testvector, Translationvector; 849 849 850 850 do { 851 851 Center.Zero(); … … 863 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 864 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 866 if ((fabs(tmp)) > BondDistance) { 867 867 flag = false; … … 879 879 cout << Verbose(1) << "vector is: "; 880 880 Testvector.Output((ofstream *)&cout); 881 cout << endl; 881 cout << endl; 882 882 #ifdef ADDHYDROGEN 883 883 // now also change all hydrogens … … 892 892 cout << Verbose(1) << "Hydrogen vector is: "; 893 893 Testvector.Output((ofstream *)&cout); 894 cout << endl; 894 cout << endl; 895 895 } 896 896 } … … 914 914 915 915 CenterGravity(out, CenterOfGravity); 916 917 // reset inertia tensor 916 917 // reset inertia tensor 918 918 for(int i=0;i<NDIM*NDIM;i++) 919 919 InertiaTensor[i] = 0.; 920 920 921 921 // sum up inertia tensor 922 922 while (ptr->next != end) { … … 943 943 } 944 944 *out << endl; 945 945 946 946 // diagonalize to determine principal axis system 947 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 952 952 gsl_eigen_symmv_free(T); 953 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 954 954 955 955 for(int i=0;i<NDIM;i++) { 956 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 957 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 958 958 } 959 959 960 960 // check whether we rotate or not 961 961 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 963 // the eigenvectors specify the transformation matrix 964 964 ptr = start; … … 972 972 973 973 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 974 // reset inertia tensor 975 975 for(int i=0;i<NDIM*NDIM;i++) 976 976 InertiaTensor[i] = 0.; 977 977 978 978 // sum up inertia tensor 979 979 ptr = start; … … 1002 1002 *out << endl; 1003 1003 } 1004 1004 1005 1005 // free everything 1006 1006 delete(CenterOfGravity); … … 1031 1031 1032 1032 CountElements(); // make sure ElementsInMolecule is up to date 1033 1033 1034 1034 // check file 1035 1035 if (input == NULL) { … … 1087 1087 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; 1088 1088 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 1090 // for (int d=0;d<NDIM;d++) 1091 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step … … 1121 1121 MDSteps++; 1122 1122 1123 1123 1124 1124 // exit 1125 1125 return true; 1126 1126 }; 1127 1127 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1129 1129 * \param n[] alignment vector. 1130 1130 */ … … 1145 1145 ptr = ptr->next; 1146 1146 tmp = ptr->x.x[0]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1148 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1149 1149 for (int j=0;j<MDSteps;j++) { 1150 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1152 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1153 1153 } 1154 } 1154 } 1155 1155 // rotate n vector 1156 1156 tmp = n->x[0]; … … 1160 1160 n->Output((ofstream *)&cout); 1161 1161 cout << endl; 1162 1162 1163 1163 // rotate on z-y plane 1164 1164 ptr = start; … … 1168 1168 ptr = ptr->next; 1169 1169 tmp = ptr->x.x[1]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1171 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1172 1172 for (int j=0;j<MDSteps;j++) { 1173 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1175 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 1176 } 1177 } 1177 } 1178 1178 // rotate n vector (for consistency check) 1179 1179 tmp = n->x[1]; 1180 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1181 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1182 1182 1183 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1184 1184 n->Output((ofstream *)&cout); … … 1191 1191 * \return true - succeeded, false - atom not found in list 1192 1192 */ 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1195 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1196 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1197 1197 else 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1199 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1200 1200 ElementCount--; … … 1206 1206 * \return true - succeeded, false - atom not found in list 1207 1207 */ 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1211 1211 }; 1212 1212 … … 1222 1222 } else { 1223 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1224 return NULL; 1224 return NULL; 1225 1225 } 1226 1226 }; … … 1271 1271 struct lsq_params *par = (struct lsq_params *)params; 1272 1272 atom *ptr = par->mol->start; 1273 1273 1274 1274 // initialize vectors 1275 1275 a.x[0] = gsl_vector_get(x,0); … … 1301 1301 { 1302 1302 int np = 6; 1303 1303 1304 1304 const gsl_multimin_fminimizer_type *T = 1305 1305 gsl_multimin_fminimizer_nmsimplex; … … 1307 1307 gsl_vector *ss; 1308 1308 gsl_multimin_function minex_func; 1309 1309 1310 1310 size_t iter = 0, i; 1311 1311 int status; 1312 1312 double size; 1313 1313 1314 1314 /* Initial vertex size vector */ 1315 1315 ss = gsl_vector_alloc (np); 1316 1316 1317 1317 /* Set all step sizes to 1 */ 1318 1318 gsl_vector_set_all (ss, 1.0); 1319 1319 1320 1320 /* Starting point */ 1321 1321 par->x = gsl_vector_alloc (np); 1322 1322 par->mol = this; 1323 1323 1324 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1325 1325 gsl_vector_set (par->x, 1, 0.0); … … 1328 1328 gsl_vector_set (par->x, 4, 0.0); 1329 1329 gsl_vector_set (par->x, 5, 1.0); 1330 1330 1331 1331 /* Initialize method and iterate */ 1332 1332 minex_func.f = &LeastSquareDistance; 1333 1333 minex_func.n = np; 1334 1334 minex_func.params = (void *)par; 1335 1335 1336 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1337 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1338 1338 1339 1339 do 1340 1340 { 1341 1341 iter++; 1342 1342 status = gsl_multimin_fminimizer_iterate(s); 1343 1343 1344 1344 if (status) 1345 1345 break; 1346 1346 1347 1347 size = gsl_multimin_fminimizer_size (s); 1348 1348 status = gsl_multimin_test_size (size, 1e-2); 1349 1349 1350 1350 if (status == GSL_SUCCESS) 1351 1351 { 1352 1352 printf ("converged to minimum at\n"); 1353 1353 } 1354 1354 1355 1355 printf ("%5d ", (int)iter); 1356 1356 for (i = 0; i < (size_t)np; i++) … … 1361 1361 } 1362 1362 while (status == GSL_CONTINUE && iter < 100); 1363 1363 1364 1364 for (i=0;i<(size_t)np;i++) 1365 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 1378 1378 int ElementNo, AtomNo; 1379 1379 CountElements(); 1380 1380 1381 1381 if (out == NULL) { 1382 1382 return false; … … 1413 1413 int ElementNo, AtomNo; 1414 1414 CountElements(); 1415 1415 1416 1416 if (out == NULL) { 1417 1417 return false; … … 1460 1460 atom *Walker = start; 1461 1461 while (Walker->next != end) { 1462 Walker = Walker->next; 1462 Walker = Walker->next; 1463 1463 #ifdef ADDHYDROGEN 1464 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 1491 1491 int No = 0; 1492 1492 time_t now; 1493 1493 1494 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1495 1495 walker = start; … … 1520 1520 int No = 0; 1521 1521 time_t now; 1522 1522 1523 1523 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1524 1524 walker = start; … … 1563 1563 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1564 1564 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1565 NoNonHydrogen++; 1565 NoNonHydrogen++; 1566 1566 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1567 1567 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 1571 1571 } 1572 1572 } else 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1574 1574 } 1575 1575 }; … … 1583 1583 ElementsInMolecule[i] = 0; 1584 1584 ElementCount = 0; 1585 1585 1586 1586 atom *walker = start; 1587 1587 while (walker->next != end) { … … 1619 1619 Binder = Binder->next; 1620 1620 if (Binder->Cyclic) 1621 No++; 1621 No++; 1622 1622 } 1623 1623 delete(BackEdgeStack); … … 1679 1679 * Generally, we use the CSD approach to bond recognition, that is the the distance 1680 1680 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 1681 * a threshold t = 0.4 Angstroem. 1681 * a threshold t = 0.4 Angstroem. 1682 1682 * To make it O(N log N) the function uses the linked-cell technique as follows: 1683 1683 * The procedure is step-wise: … … 1694 1694 * \param IsAngstroem whether coordinate system is gauged to Angstroem or Bohr radii 1695 1695 */ 1696 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input)// ofstream* out, double bonddistance, bool IsAngstroem) 1697 { 1698 1699 // 1 We will parse bonds out of the dbond file created by tremolo. 1700 int atom1, atom2, temp; 1701 atom *Walker, *OtherWalker; 1702 1703 if (!input) 1704 { 1705 cout << Verbose(1) << "Opening silica failed \n"; 1706 }; 1707 1708 *input >> ws >> atom1; 1709 *input >> ws >> atom2; 1710 cout << Verbose(1) << "Scanning file\n"; 1711 while (!input->eof()) // Check whether we read 2 items 1712 { 1713 *input >> ws >> atom1; 1714 *input >> ws >> atom2; 1715 if(atom2<atom1) //Sort indizes of atoms in order 1716 { 1717 temp=atom1; 1718 atom1=atom2; 1719 atom2=temp; 1720 }; 1721 1722 Walker=start; 1723 while(Walker-> nr != atom1) // Find atom corresponding to first index 1724 { 1725 Walker = Walker->next; 1726 }; 1727 OtherWalker = Walker->next; 1728 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1729 { 1730 OtherWalker= OtherWalker->next; 1731 }; 1732 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1733 BondCount++; //Increase bond count of molecule 1734 } 1735 1736 CreateListOfBondsPerAtom(out); 1737 1738 }; 1696 1739 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 1697 1740 { 1741 1698 1742 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1699 1743 int No, NoBonds, CandidateBondNo; … … 1704 1748 Vector x; 1705 1749 int FalseBondDegree = 0; 1706 1750 1707 1751 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1708 1752 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 1711 1755 cleanup(first,last); 1712 1756 } 1713 1757 1714 1758 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1715 1759 CountAtoms(out); … … 1730 1774 for (int i=NumberCells;i--;) 1731 1775 CellList[i] = NULL; 1732 1776 1733 1777 // 2b. put all atoms into its corresponding list 1734 1778 Walker = start; … … 1751 1795 if (CellList[index] == NULL) // allocate molecule if not done 1752 1796 CellList[index] = new molecule(elemente); 1753 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1754 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1797 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1798 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1755 1799 } 1756 1800 //for (int i=0;i<NumberCells;i++) 1757 1801 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1758 1802 1803 1759 1804 // 3a. go through every cell 1760 1805 for (N[0]=divisor[0];N[0]--;) … … 1769 1814 Walker = Walker->next; 1770 1815 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1771 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1816 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1772 1817 for (n[0]=-1;n[0]<=1;n[0]++) 1773 1818 for (n[1]=-1;n[1]<=1;n[1]++) … … 1801 1846 } 1802 1847 } 1848 1849 1850 1803 1851 // 4. free the cell again 1804 1852 for (int i=NumberCells;i--;) … … 1807 1855 } 1808 1856 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1809 1857 1810 1858 // create the adjacency list per atom 1811 1859 CreateListOfBondsPerAtom(out); 1812 1860 1813 1861 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1814 1862 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 1859 1907 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1860 1908 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1861 1909 1862 1910 // output bonds for debugging (if bond chain list was correctly installed) 1863 1911 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 1869 1917 *out << endl; 1870 1918 } else 1871 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1919 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1872 1920 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1873 1921 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1874 }; 1922 1923 }; 1924 1925 1875 1926 1876 1927 /** Performs a Depth-First search on this molecule. … … 1893 1944 bond *Binder = NULL; 1894 1945 bool BackStepping = false; 1895 1946 1896 1947 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1897 1948 1898 1949 ResetAllBondsToUnused(); 1899 1950 ResetAllAtomNumbers(); … … 1908 1959 LeafWalker->Leaf = new molecule(elemente); 1909 1960 LeafWalker->Leaf->AddCopyAtom(Root); 1910 1961 1911 1962 OldGraphNr = CurrentGraphNr; 1912 1963 Walker = Root; … … 1919 1970 AtomStack->Push(Walker); 1920 1971 CurrentGraphNr++; 1921 } 1972 } 1922 1973 do { // (3) if Walker has no unused egdes, go to (5) 1923 1974 BackStepping = false; // reset backstepping flag for (8) … … 1953 2004 Binder = NULL; 1954 2005 } while (1); // (2) 1955 2006 1956 2007 // 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! 1957 2008 if ((Walker == Root) && (Binder == NULL)) 1958 2009 break; 1959 1960 // (5) if Ancestor of Walker is ... 2010 2011 // (5) if Ancestor of Walker is ... 1961 2012 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 1962 2013 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2001 2052 } while (OtherAtom != Walker); 2002 2053 ComponentNumber++; 2003 2054 2004 2055 // (11) Root is separation vertex, set Walker to Root and go to (4) 2005 2056 Walker = Root; … … 2014 2065 2015 2066 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2016 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2067 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2017 2068 LeafWalker->Leaf->Output(out); 2018 2069 *out << endl; … … 2022 2073 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2023 2074 if (Root->GraphNr != -1) // if already discovered, step on 2024 Root = Root->next; 2075 Root = Root->next; 2025 2076 } 2026 2077 } … … 2044 2095 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2045 2096 } 2046 2097 2047 2098 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2048 2099 Binder = first; … … 2055 2106 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2056 2107 OutputComponentNumber(out, Binder->rightatom); 2057 *out << ">." << endl; 2108 *out << ">." << endl; 2058 2109 if (Binder->Cyclic) // cyclic ?? 2059 2110 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2070 2121 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2071 2122 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2072 * as cyclic and print out the cycles. 2123 * as cyclic and print out the cycles. 2073 2124 * \param *out output stream for debugging 2074 2125 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph! … … 2081 2132 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2082 2133 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2083 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2134 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2084 2135 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2085 2136 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2093 2144 ColorList[i] = white; 2094 2145 } 2095 2146 2096 2147 *out << Verbose(1) << "Back edge list - "; 2097 2148 BackEdgeStack->Output(out); 2098 2149 2099 2150 *out << Verbose(1) << "Analysing cycles ... " << endl; 2100 2151 NumCycles = 0; … … 2102 2153 BackEdge = BackEdgeStack->PopFirst(); 2103 2154 // this is the target 2104 Root = BackEdge->leftatom; 2155 Root = BackEdge->leftatom; 2105 2156 // this is the source point 2106 Walker = BackEdge->rightatom; 2157 Walker = BackEdge->rightatom; 2107 2158 ShortestPathList[Walker->nr] = 0; 2108 2159 BFSStack->ClearStack(); // start with empty BFS stack … … 2118 2169 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2119 2170 OtherAtom = Binder->GetOtherAtom(Walker); 2120 #ifdef ADDHYDROGEN 2171 #ifdef ADDHYDROGEN 2121 2172 if (OtherAtom->type->Z != 1) { 2122 2173 #endif … … 2127 2178 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2128 2179 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2129 *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; 2180 *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; 2130 2181 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2131 2182 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2137 2188 if (OtherAtom == Root) 2138 2189 break; 2139 #ifdef ADDHYDROGEN 2190 #ifdef ADDHYDROGEN 2140 2191 } else { 2141 2192 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2175 2226 } 2176 2227 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2177 2228 2178 2229 if (OtherAtom == Root) { 2179 2230 // now climb back the predecessor list and thus find the cycle members … … 2203 2254 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2204 2255 } 2205 2256 2206 2257 // now clean the lists 2207 2258 while (!TouchedStack->IsEmpty()){ … … 2213 2264 } 2214 2265 if (MinRingSize != -1) { 2215 // go over all atoms 2266 // go over all atoms 2216 2267 Root = start; 2217 2268 while(Root->next != end) { 2218 2269 Root = Root->next; 2219 2270 2220 2271 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2221 2272 Walker = Root; … … 2254 2305 } 2255 2306 ColorList[Walker->nr] = black; 2256 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2307 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2257 2308 } 2258 2309 2259 2310 // now clean the lists 2260 2311 while (!TouchedStack->IsEmpty()){ … … 2305 2356 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2306 2357 { 2307 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2358 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2308 2359 *out << vertex->ComponentNr[i] << " "; 2309 2360 }; … … 2383 2434 { 2384 2435 int c = 0; 2385 int FragmentCount; 2436 int FragmentCount; 2386 2437 // get maximum bond degree 2387 2438 atom *Walker = start; … … 2393 2444 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2394 2445 return FragmentCount; 2395 }; 2446 }; 2396 2447 2397 2448 /** Scans a single line for number and puts them into \a KeySet. 2398 2449 * \param *out output stream for debugging 2399 2450 * \param *buffer buffer to scan 2400 * \param &CurrentSet filled KeySet on return 2451 * \param &CurrentSet filled KeySet on return 2401 2452 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 2402 2453 */ … … 2406 2457 int AtomNr; 2407 2458 int status = 0; 2408 2459 2409 2460 line.str(buffer); 2410 2461 while (!line.eof()) { … … 2442 2493 double TEFactor; 2443 2494 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2444 2495 2445 2496 if (FragmentList == NULL) { // check list pointer 2446 2497 FragmentList = new Graph; 2447 2498 } 2448 2499 2449 2500 // 1st pass: open file and read 2450 2501 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 2475 2526 status = false; 2476 2527 } 2477 2528 2478 2529 // 2nd pass: open TEFactors file and read 2479 2530 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 2487 2538 InputFile >> TEFactor; 2488 2539 (*runner).second.second = TEFactor; 2489 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2540 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2490 2541 } else { 2491 2542 status = false; … … 2528 2579 if(output != NULL) { 2529 2580 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2530 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2581 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2531 2582 if (sprinter != (*runner).first.begin()) 2532 2583 output << "\t"; … … 2594 2645 status = false; 2595 2646 } 2596 2647 2597 2648 return status; 2598 2649 }; … … 2603 2654 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 2604 2655 * \return true - structure is equal, false - not equivalence 2605 */ 2656 */ 2606 2657 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2607 2658 { … … 2610 2661 bool status = true; 2611 2662 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2612 2663 2613 2664 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2614 2665 File.open(filename.str().c_str(), ios::out); … … 2669 2720 *out << endl; 2670 2721 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2671 2722 2672 2723 return status; 2673 2724 }; … … 2691 2742 for(int i=AtomCount;i--;) 2692 2743 AtomMask[i] = false; 2693 2744 2694 2745 if (Order < 0) { // adaptive increase of BondOrder per site 2695 2746 if (AtomMask[AtomCount] == true) // break after one step … … 2731 2782 line >> ws >> Value; // skip time entry 2732 2783 line >> ws >> Value; 2733 No -= 1; // indices start at 1 in file, not 0 2784 No -= 1; // indices start at 1 in file, not 0 2734 2785 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2735 2786 … … 2740 2791 // 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 2741 2792 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2742 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2793 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2743 2794 if (!InsertedElement.second) { // this root is already present 2744 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2745 //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) 2795 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2796 //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) 2746 2797 { // if value is smaller, update value and order 2747 2798 (*PresentItem).second.first = fabs(Value); … … 2781 2832 Walker = FindAtom(No); 2782 2833 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2783 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2834 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2784 2835 AtomMask[No] = true; 2785 2836 status = true; 2786 2837 //} else 2787 //*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; 2838 //*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; 2788 2839 } 2789 2840 // close and done … … 2819 2870 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2820 2871 status = true; 2821 2872 2822 2873 if (!status) { 2823 2874 if (Order == 0) … … 2827 2878 } 2828 2879 } 2829 2880 2830 2881 // print atom mask for debugging 2831 2882 *out << " "; … … 2836 2887 *out << (AtomMask[i] ? "t" : "f"); 2837 2888 *out << endl; 2838 2889 2839 2890 return status; 2840 2891 }; … … 2850 2901 int AtomNo = 0; 2851 2902 atom *Walker = NULL; 2852 2903 2853 2904 if (SortIndex != NULL) { 2854 2905 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 2908 2959 atom **ListOfAtoms = NULL; 2909 2960 atom ***ListOfLocalAtoms = NULL; 2910 bool *AtomMask = NULL; 2911 2961 bool *AtomMask = NULL; 2962 2912 2963 *out << endl; 2913 2964 #ifdef ADDHYDROGEN … … 2918 2969 2919 2970 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 2920 2971 2921 2972 // ===== 1. Check whether bond structure is same as stored in files ==== 2922 2973 2923 2974 // fill the adjacency list 2924 2975 CreateListOfBondsPerAtom(out); … … 2926 2977 // create lookup table for Atom::nr 2927 2978 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 2928 2979 2929 2980 // === compare it with adjacency file === 2930 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2981 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2931 2982 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2932 2983 … … 2957 3008 delete(LocalBackEdgeStack); 2958 3009 } 2959 3010 2960 3011 // ===== 3. if structure still valid, parse key set file and others ===== 2961 3012 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 2963 3014 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 2964 3015 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 2965 2966 // =================================== Begin of FRAGMENTATION =============================== 2967 // ===== 6a. assign each keyset to its respective subgraph ===== 3016 3017 // =================================== Begin of FRAGMENTATION =============================== 3018 // ===== 6a. assign each keyset to its respective subgraph ===== 2968 3019 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 2969 3020 … … 2976 3027 FragmentationToDo = FragmentationToDo || CheckOrder; 2977 3028 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 2978 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3029 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 2979 3030 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 2980 3031 … … 3000 3051 delete(ParsedFragmentList); 3001 3052 delete[](MinimumRingSize); 3002 3053 3003 3054 3004 3055 // ==================================== End of FRAGMENTATION ============================================ … … 3006 3057 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3007 3058 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3008 3059 3009 3060 // free subgraph memory again 3010 3061 FragmentCounter = 0; … … 3031 3082 } 3032 3083 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3033 3084 3034 3085 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3035 3086 if (BondFragments->NumberOfMolecules != 0) { 3036 3087 // create the SortIndex from BFS labels to order in the config file 3037 3088 CreateMappingLabelsToConfigSequence(out, SortIndex); 3038 3089 3039 3090 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3040 3091 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) … … 3042 3093 else 3043 3094 *out << Verbose(1) << "Some config writing failed." << endl; 3044 3095 3045 3096 // store force index reference file 3046 3097 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3047 3048 // store keysets file 3098 3099 // store keysets file 3049 3100 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3050 3051 // store Adjacency file 3101 3102 // store Adjacency file 3052 3103 StoreAdjacencyToFile(out, configuration->configpath); 3053 3104 3054 3105 // store Hydrogen saturation correction file 3055 3106 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3056 3107 3057 3108 // store adaptive orders into file 3058 3109 StoreOrderAtSiteFile(out, configuration->configpath); 3059 3110 3060 3111 // restore orbital and Stop values 3061 3112 CalculateOrbitals(*configuration); 3062 3113 3063 3114 // free memory for bond part 3064 3115 *out << Verbose(1) << "Freeing bond memory" << endl; 3065 3116 delete(FragmentList); // remove bond molecule from memory 3066 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3117 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3067 3118 } else 3068 3119 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3069 //} else 3120 //} else 3070 3121 // *out << Verbose(1) << "No fragments to store." << endl; 3071 3122 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3093 3144 atom *Walker = NULL, *OtherAtom = NULL; 3094 3145 ReferenceStack->Push(Binder); 3095 3146 3096 3147 do { // go through all bonds and push local ones 3097 3148 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3098 if (Walker != NULL) // if this Walker exists in the subgraph ... 3149 if (Walker != NULL) // if this Walker exists in the subgraph ... 3099 3150 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3100 3151 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); … … 3109 3160 ReferenceStack->Push(Binder); 3110 3161 } while (FirstBond != Binder); 3111 3162 3112 3163 return status; 3113 3164 }; … … 3185 3236 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3186 3237 Walker->MaxOrder = MaxArray[Walker->nr]; 3187 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3238 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3188 3239 } 3189 3240 file.close(); … … 3196 3247 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3197 3248 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3198 3249 3199 3250 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3200 3251 return status; … … 3254 3305 Walker = start; 3255 3306 while (Walker->next != end) { 3256 Walker = Walker->next; 3307 Walker = Walker->next; 3257 3308 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3258 3309 TotalDegree = 0; … … 3262 3313 } 3263 3314 *out << " -- TotalDegree: " << TotalDegree << endl; 3264 } 3315 } 3265 3316 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3266 3317 }; … … 3268 3319 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3269 3320 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3270 * white and putting into queue. 3321 * white and putting into queue. 3271 3322 * \param *out output stream for debugging 3272 3323 * \param *Mol Molecule class to add atoms to … … 3277 3328 * \param BondOrder maximum distance for vertices to add 3278 3329 * \param IsAngstroem lengths are in angstroem or bohrradii 3279 */ 3330 */ 3280 3331 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3281 3332 { … … 3303 3354 } 3304 3355 ShortestPathList[Root->nr] = 0; 3305 3356 3306 3357 // and go on ... Queue always contains all lightgray vertices 3307 3358 while (!AtomStack->IsEmpty()) { … … 3311 3362 // followed by n+1 till top of stack. 3312 3363 Walker = AtomStack->PopFirst(); // pop oldest added 3313 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3364 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3314 3365 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3315 3366 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3318 3369 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3319 3370 if (ColorList[OtherAtom->nr] == white) { 3320 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) 3371 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) 3321 3372 ColorList[OtherAtom->nr] = lightgray; 3322 3373 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3323 3374 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3324 *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; 3375 *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; 3325 3376 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3326 3377 *out << Verbose(3); … … 3370 3421 // This has to be a cyclic bond, check whether it's present ... 3371 3422 if (AddedBondList[Binder->nr] == NULL) { 3372 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3423 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3373 3424 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3374 3425 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3385 3436 } 3386 3437 ColorList[Walker->nr] = black; 3387 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3438 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3388 3439 } 3389 3440 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 3409 3460 3410 3461 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3411 3462 3412 3463 // reset parent list 3413 3464 *out << Verbose(3) << "Resetting ParentList." << endl; 3414 3465 for (int i=Father->AtomCount;i--;) 3415 3466 ParentList[i] = NULL; 3416 3467 3417 3468 // fill parent list with sons 3418 3469 *out << Verbose(3) << "Filling Parent List." << endl; … … 3455 3506 * \param *&Leaf KeySet to look through 3456 3507 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 3457 * \param index of the atom suggested for removal 3508 * \param index of the atom suggested for removal 3458 3509 */ 3459 3510 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 3461 3512 atom *Runner = NULL; 3462 3513 int SP, Removal; 3463 3514 3464 3515 *out << Verbose(2) << "Looking for removal candidate." << endl; 3465 3516 SP = -1; //0; // not -1, so that Root is never removed … … 3479 3530 /** Stores a fragment from \a KeySet into \a molecule. 3480 3531 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 3481 * molecule and adds missing hydrogen where bonds were cut. 3532 * molecule and adds missing hydrogen where bonds were cut. 3482 3533 * \param *out output stream for debugging messages 3483 * \param &Leaflet pointer to KeySet structure 3534 * \param &Leaflet pointer to KeySet structure 3484 3535 * \param IsAngstroem whether we have Ansgtroem or bohrradius 3485 3536 * \return pointer to constructed molecule … … 3492 3543 bool LonelyFlag = false; 3493 3544 int size; 3494 3545 3495 3546 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3496 3547 3497 3548 Leaf->BondDistance = BondDistance; 3498 3549 for(int i=NDIM*2;i--;) 3499 Leaf->cell_size[i] = cell_size[i]; 3550 Leaf->cell_size[i] = cell_size[i]; 3500 3551 3501 3552 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 3510 3561 size++; 3511 3562 } 3512 3563 3513 3564 // create the bonds between all: Make it an induced subgraph and add hydrogen 3514 3565 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 3520 3571 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3521 3572 // create all bonds 3522 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3573 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3523 3574 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3524 3575 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3525 3576 if (SonList[OtherFather->nr] != NULL) { 3526 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3577 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3527 3578 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3528 3579 // *out << Verbose(3) << "Adding Bond: "; 3529 // *out << 3580 // *out << 3530 3581 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3531 3582 // *out << "." << endl; 3532 3583 //NumBonds[Runner->nr]++; 3533 } else { 3584 } else { 3534 3585 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3535 3586 } 3536 3587 LonelyFlag = false; 3537 3588 } else { 3538 // *out << ", who has no son in this fragment molecule." << endl; 3589 // *out << ", who has no son in this fragment molecule." << endl; 3539 3590 #ifdef ADDHYDROGEN 3540 3591 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; … … 3554 3605 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3555 3606 Runner = Runner->next; 3556 #endif 3607 #endif 3557 3608 } 3558 3609 Leaf->CreateListOfBondsPerAtom(out); … … 3587 3638 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 3588 3639 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack! 3589 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3640 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3590 3641 MoleculeListClass *FragmentList = NULL; 3591 3642 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 3637 3688 // clear snake stack 3638 3689 SnakeStack->ClearStack(); 3639 //SnakeStack->TestImplementation(out, start->next); 3690 //SnakeStack->TestImplementation(out, start->next); 3640 3691 3641 3692 ///// INNER LOOP //////////// … … 3658 3709 } 3659 3710 if (ShortestPathList[Walker->nr] == -1) { 3660 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3711 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3661 3712 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 3662 3713 } … … 3696 3747 OtherAtom = Binder->GetOtherAtom(Walker); 3697 3748 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 3698 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3749 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3699 3750 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 3700 3751 } else { // otherwise check its colour and element 3701 3752 if ( 3702 3753 #ifdef ADDHYDROGEN 3703 (OtherAtom->type->Z != 1) && 3754 (OtherAtom->type->Z != 1) && 3704 3755 #endif 3705 3756 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 3711 3762 //} else { 3712 3763 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3713 //} 3764 //} 3714 3765 Walker = OtherAtom; 3715 3766 break; 3716 3767 } else { 3717 if (OtherAtom->type->Z == 1) 3768 if (OtherAtom->type->Z == 1) 3718 3769 *out << "Links to a hydrogen atom." << endl; 3719 else 3770 else 3720 3771 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 3721 3772 } … … 3727 3778 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 3728 3779 } 3729 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3780 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3730 3781 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 3731 3782 ColorVertexList[Walker->nr] = black; … … 3734 3785 } 3735 3786 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 3736 *out << Verbose(2) << "Inner Looping is finished." << endl; 3787 *out << Verbose(2) << "Inner Looping is finished." << endl; 3737 3788 3738 3789 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 3750 3801 } 3751 3802 } 3752 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3803 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3753 3804 3754 3805 // copy together 3755 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3806 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3756 3807 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 3757 3808 RunningIndex = 0; … … 3824 3875 3825 3876 NumCombinations = 1 << SetDimension; 3826 3877 3827 3878 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3828 3879 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3829 3880 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3830 3881 3831 3882 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3832 3883 *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; 3833 3884 3834 // initialised touched list (stores added atoms on this level) 3885 // initialised touched list (stores added atoms on this level) 3835 3886 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3836 3887 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3837 3888 TouchedList[TouchedIndex] = -1; 3838 3889 TouchedIndex = 0; 3839 3890 3840 3891 // create every possible combination of the endpieces 3841 3892 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 3845 3896 for (int j=SetDimension;j--;) 3846 3897 bits += (i & (1 << j)) >> j; 3847 3898 3848 3899 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3849 3900 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 3853 3904 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3854 3905 if (bit) { // if bit is set, we add this bond partner 3855 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3906 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3856 3907 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3857 3908 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3858 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3909 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3859 3910 if (TestKeySetInsert.second) { 3860 3911 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 3869 3920 } 3870 3921 } 3871 3872 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3922 3923 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3873 3924 if (SpaceLeft > 0) { 3874 3925 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 3898 3949 } 3899 3950 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3900 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3951 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3901 3952 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3902 3953 } … … 3907 3958 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3908 3959 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3909 *out << (*runner) << " "; 3960 *out << (*runner) << " "; 3910 3961 *out << endl; 3911 3962 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 3915 3966 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3916 3967 } 3917 3968 3918 3969 // --3-- remove all added items in this level from snake stack 3919 3970 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 3926 3977 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3927 3978 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3928 *out << (*runner) << " "; 3979 *out << (*runner) << " "; 3929 3980 *out << endl; 3930 3981 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 3933 3984 } 3934 3985 } 3935 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3986 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3936 3987 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3937 3988 }; … … 3942 3993 * \return true - connected, false - disconnected 3943 3994 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 3944 */ 3995 */ 3945 3996 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3946 3997 { … … 3948 3999 bool BondStatus = false; 3949 4000 int size; 3950 4001 3951 4002 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3952 4003 *out << Verbose(2) << "Disconnected atom: "; 3953 4004 3954 4005 // count number of atoms in graph 3955 4006 size = 0; … … 3997 4048 * \param *out output stream for debugging 3998 4049 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 3999 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4050 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4000 4051 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4001 4052 * \return number of inserted fragments 4002 4053 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4003 4054 */ 4004 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4055 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4005 4056 { 4006 4057 int SP, AtomKeyNr; … … 4023 4074 FragmentSearch.BondsPerSPCount[i] = 0; 4024 4075 FragmentSearch.BondsPerSPCount[0] = 1; 4025 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4076 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4026 4077 add(Binder, FragmentSearch.BondsPerSPList[1]); 4027 4078 4028 4079 // do a BFS search to fill the SP lists and label the found vertices 4029 4080 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4030 4081 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4031 4082 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4032 // (EdgeinSPLevel) of this tree ... 4083 // (EdgeinSPLevel) of this tree ... 4033 4084 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4034 4085 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4083 4134 } 4084 4135 } 4085 4136 4086 4137 // outputting all list for debugging 4087 4138 *out << Verbose(0) << "Printing all found lists." << endl; … … 4092 4143 Binder = Binder->next; 4093 4144 *out << Verbose(2) << *Binder << endl; 4094 } 4095 } 4096 4145 } 4146 } 4147 4097 4148 // creating fragments with the found edge sets (may be done in reverse order, faster) 4098 4149 SP = -1; // the Root <-> Root edge must be subtracted! … … 4101 4152 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4102 4153 Binder = Binder->next; 4103 SP ++; 4154 SP ++; 4104 4155 } 4105 4156 } … … 4108 4159 // start with root (push on fragment stack) 4109 4160 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4110 FragmentSearch.FragmentSet->clear(); 4161 FragmentSearch.FragmentSet->clear(); 4111 4162 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4112 4163 // prepare the subset and call the generator 4113 4164 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4114 4165 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4115 4166 4116 4167 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4117 4168 4118 4169 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4119 4170 } else { … … 4124 4175 // remove root from stack 4125 4176 *out << Verbose(0) << "Removing root again from stack." << endl; 4126 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4177 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4127 4178 4128 4179 // free'ing the bonds lists … … 4143 4194 } 4144 4195 4145 // return list 4196 // return list 4146 4197 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4147 4198 return (FragmentSearch.FragmentCounter - Counter); … … 4174 4225 // remove bonds that are beyond bonddistance 4175 4226 for(int i=NDIM;i--;) 4176 Translationvector.x[i] = 0.; 4227 Translationvector.x[i] = 0.; 4177 4228 // scan all bonds 4178 4229 Binder = first; … … 4221 4272 } 4222 4273 } 4223 // re-add bond 4274 // re-add bond 4224 4275 link(Binder, OtherBinder); 4225 4276 } else { … … 4275 4326 IteratorB++; 4276 4327 } // end of while loop 4277 }// end of check in case of equal sizes 4328 }// end of check in case of equal sizes 4278 4329 } 4279 4330 return false; // if we reach this point, they are equal … … 4319 4370 * \param graph1 first (dest) graph 4320 4371 * \param graph2 second (source) graph 4321 * \param *counter keyset counter that gets increased 4372 * \param *counter keyset counter that gets increased 4322 4373 */ 4323 4374 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 4364 4415 int RootKeyNr, RootNr; 4365 4416 struct UniqueFragments FragmentSearch; 4366 4417 4367 4418 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4368 4419 … … 4387 4438 Walker = Walker->next; 4388 4439 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4389 } 4440 } 4390 4441 4391 4442 // 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 … … 4401 4452 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4402 4453 // *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; 4403 //} else 4454 //} else 4404 4455 { 4405 4456 // increase adaptive order by one 4406 4457 Walker->GetTrueFather()->AdaptiveOrder++; 4407 4458 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4408 4459 4409 4460 // initialise Order-dependent entries of UniqueFragments structure 4410 4461 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 4413 4464 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4414 4465 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4415 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4466 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4416 4467 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4417 4468 FragmentSearch.BondsPerSPCount[i] = 0; 4418 } 4419 4469 } 4470 4420 4471 // allocate memory for all lower level orders in this 1D-array of ptrs 4421 4472 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 4423 4474 for (int i=0;i<NumLevels;i++) 4424 4475 FragmentLowerOrdersList[RootNr][i] = NULL; 4425 4476 4426 4477 // create top order where nothing is reduced 4427 4478 *out << Verbose(0) << "==============================================================================================================" << endl; 4428 4479 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4429 4480 4430 4481 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4431 4482 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 4440 4491 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4441 4492 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4442 4493 4443 4494 // if ((NumLevels >> 1) > 0) { 4444 4495 // // create lower order fragments … … 4447 4498 // 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) 4448 4499 // // step down to next order at (virtual) boundary of powers of 2 in array 4449 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4500 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4450 4501 // Order--; 4451 4502 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 4454 4505 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4455 4506 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4456 // 4507 // 4457 4508 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4458 4509 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 4485 4536 RootStack.push_back(RootKeyNr); // put back on stack 4486 4537 RootNr++; 4487 4538 4488 4539 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4489 4540 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 4491 4542 delete(FragmentSearch.BondsPerSPList[2*i]); 4492 4543 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4493 } 4544 } 4494 4545 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4495 4546 } … … 4502 4553 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4503 4554 delete(FragmentSearch.FragmentSet); 4504 4505 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4555 4556 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4506 4557 // 5433222211111111 4507 4558 // 43221111 … … 4523 4574 RootKeyNr = RootStack.front(); 4524 4575 RootStack.pop_front(); 4525 Walker = FindAtom(RootKeyNr); 4576 Walker = FindAtom(RootKeyNr); 4526 4577 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4527 4578 for(int i=0;i<NumLevels;i++) { … … 4536 4587 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4537 4588 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4538 4589 4539 4590 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4540 4591 }; … … 4570 4621 atom *Walker = NULL; 4571 4622 bool result = true; // status of comparison 4572 4573 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4623 4624 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4574 4625 /// first count both their atoms and elements and update lists thereby ... 4575 4626 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 4618 4669 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 4619 4670 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4620 result = false; 4621 } 4622 } 4623 4671 result = false; 4672 } 4673 } 4674 4624 4675 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4625 4676 if (result) { … … 4637 4688 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 4638 4689 } 4639 4690 4640 4691 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4641 4692 *out << Verbose(5) << "Sorting distances" << endl; … … 4648 4699 for(int i=AtomCount;i--;) 4649 4700 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4650 4701 4651 4702 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4652 4703 *out << Verbose(4) << "Comparing distances" << endl; … … 4659 4710 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4660 4711 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4661 4712 4662 4713 /// free memory 4663 4714 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 4667 4718 result = false; 4668 4719 } 4669 } 4720 } 4670 4721 /// return pointer to map if all distances were below \a threshold 4671 4722 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 4676 4727 *out << Verbose(3) << "Result: Not equal." << endl; 4677 4728 return NULL; 4678 } 4729 } 4679 4730 }; 4680 4731 … … 4731 4782 * \param *output output stream of temperature file 4732 4783 * \return file written (true), failure on writing file (false) 4733 */ 4784 */ 4734 4785 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4735 4786 { … … 4739 4790 if (output == NULL) 4740 4791 return false; 4741 else 4792 else 4742 4793 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4743 4794 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
src/molecules.hpp
r1ffa21 r69eb71 1 1 /** \file molecules.hpp 2 2 * 3 * Class definitions of atom and molecule, element and periodentafel 3 * Class definitions of atom and molecule, element and periodentafel 4 4 */ 5 5 … … 54 54 #define BoundariesTestPair pair< Boundaries::iterator, bool> 55 55 56 #define PointMap map < int, class BoundaryPointSet * > 57 #define PointPair pair < int, class BoundaryPointSet * > 58 #define PointTestPair pair < PointMap::iterator, bool > 59 60 #define LineMap map < int, class BoundaryLineSet * > 61 #define LinePair pair < int, class BoundaryLineSet * > 62 #define LineTestPair pair < LinePair::iterator, bool > 63 64 #define TriangleMap map < int, class BoundaryTriangleSet * > 65 #define TrianglePair pair < int, class BoundaryTriangleSet * > 66 #define TriangleTestPair pair < TrianglePair::iterator, bool > 56 #define PointMap map < int, class BoundaryPointSet * > 57 #define PointPair pair < int, class BoundaryPointSet * > 58 #define PointTestPair pair < PointMap::iterator, bool > 59 60 #define LineMap map < int, class BoundaryLineSet * > 61 #define LinePair pair < int, class BoundaryLineSet * > 62 #define LineTestPair pair < LinePair::iterator, bool > 63 64 #define TriangleMap map < int, class BoundaryTriangleSet * > 65 #define TrianglePair pair < int, class BoundaryTriangleSet * > 66 #define TriangleTestPair pair < TrianglePair::iterator, bool > 67 67 68 68 #define DistanceMultiMap multimap <double, pair < PointMap::iterator, PointMap::iterator> > … … 86 86 //bool operator < (KeySet SubgraphA, KeySet SubgraphB); //note: this declaration is important, otherwise normal < is used (producing wrong order) 87 87 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment); // Insert a KeySet into a Graph 88 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 88 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter); // Insert all KeySet's in a Graph into another Graph 89 89 int CompareDoubles (const void * a, const void * b); 90 90 … … 140 140 unsigned char AdaptiveOrder; //!< current present bond order at site (0 means "not set") 141 141 bool MaxOrder; //!< whether this atom as a root in fragmentation still creates more fragments on higher orders or not 142 142 143 143 atom(); 144 144 ~atom(); 145 145 146 146 bool Output(int ElementNo, int AtomNo, ofstream *out) const; 147 147 bool OutputXYZLine(ofstream *out) const; 148 148 atom *GetTrueFather(); 149 149 bool Compare(atom &ptr); 150 150 151 151 private: 152 152 }; … … 169 169 int nr; //!< unique number in a molecule, updated by molecule::CreateAdjacencyList() 170 170 bool Cyclic; //!< flag whether bond is part of a cycle or not, given in DepthFirstSearchAnalysis() 171 enum EdgeType Type;//!< whether this is a tree or back edge 172 171 enum EdgeType Type;//!< whether this is a tree or back edge 172 173 173 atom * GetOtherAtom(atom *Atom) const; 174 174 bond * GetFirstBond(); 175 175 bond * GetLastBond(); 176 176 177 177 bool MarkUsed(enum Shading color); 178 178 enum Shading IsUsed(); … … 180 180 bool Contains(const atom *ptr); 181 181 bool Contains(const int nr); 182 182 183 183 bond(); 184 184 bond(atom *left, atom *right); … … 186 186 bond(atom *left, atom *right, int degree, int number); 187 187 ~bond(); 188 189 private: 188 189 private: 190 190 enum Shading Used; //!< marker in depth-first search, DepthFirstSearchAnalysis() 191 191 }; … … 218 218 int NoCyclicBonds; //!< number of cyclic bonds in molecule, by DepthFirstSearchAnalysis() 219 219 double BondDistance; //!< typical bond distance used in CreateAdjacencyList() and furtheron 220 220 221 221 molecule(periodentafel *teil); 222 222 ~molecule(); 223 223 224 224 /// remove atoms from molecule. 225 225 bool AddAtom(atom *pointer); … … 230 230 atom * AddCopyAtom(atom *pointer); 231 231 bool AddXYZFile(string filename); 232 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 232 bool AddHydrogenReplacementAtom(ofstream *out, bond *Bond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem); 233 233 bond * AddBond(atom *first, atom *second, int degree); 234 234 bool RemoveBond(bond *pointer); 235 235 bool RemoveBonds(atom *BondPartner); 236 236 237 237 /// Find atoms. 238 atom * FindAtom(int Nr) const; 238 atom * FindAtom(int Nr) const; 239 239 atom * AskAtom(string text); 240 240 … … 244 244 void CalculateOrbitals(class config &configuration); 245 245 bool CenterInBox(ofstream *out, Vector *BoxLengths); 246 void CenterEdge(ofstream *out, Vector *max); 247 void CenterOrigin(ofstream *out, Vector *max); 246 void CenterEdge(ofstream *out, Vector *max); 247 void CenterOrigin(ofstream *out, Vector *max); 248 248 void CenterGravity(ofstream *out, Vector *max); 249 249 void Translate(const Vector *x); … … 260 260 double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem); 261 261 bool VerletForceIntegration(char *file, double delta_t, bool IsAngstroem); 262 262 263 263 bool CheckBounds(const Vector *x) const; 264 264 void GetAlignvector(struct lsq_params * par) const; 265 265 266 /// Initialising routines in fragmentation 266 /// Initialising routines in fragmentation 267 void CreateAdjacencyList2(ofstream *out, ifstream *output); 267 268 void CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem); 268 269 void CreateListOfBondsPerAtom(ofstream *out); 269 270 270 271 // Graph analysis 271 272 MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack); … … 283 284 284 285 molecule *CopyMolecule(); 285 286 286 287 /// Fragment molecule by two different approaches: 287 288 int FragmentMolecule(ofstream *out, int Order, config *configuration); … … 305 306 int LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList); 306 307 int GuesstimateFragmentCount(ofstream *out, int order); 307 308 // Recognize doubly appearing molecules in a list of them 308 309 // Recognize doubly appearing molecules in a list of them 309 310 int * IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold); 310 311 int * GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule); 311 312 312 313 // Output routines. 313 314 bool Output(ofstream *out); … … 330 331 int NumberOfMolecules; //!< Number of entries in \a **FragmentList and of to be returned one. 331 332 int NumberOfTopAtoms; //!< Number of atoms in the molecule from which all fragments originate 332 333 333 334 MoleculeListClass(); 334 335 MoleculeListClass(int Num, int NumAtoms); … … 340 341 bool OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex); 341 342 void Output(ofstream *out); 342 343 343 344 private: 344 345 }; … … 350 351 class MoleculeLeafClass { 351 352 public: 352 molecule *Leaf; //!< molecule of this leaf 353 molecule *Leaf; //!< molecule of this leaf 353 354 //MoleculeLeafClass *UpLeaf; //!< Leaf one level up 354 355 //MoleculeLeafClass *DownLeaf; //!< First leaf one level down … … 386 387 bool FastParsing; 387 388 double Deltat; 388 389 389 390 private: 390 391 char *mainname; 391 392 char *defaultpath; 392 393 char *pseudopotpath; 393 394 394 395 int DoOutVis; 395 396 int DoOutMes; … … 406 407 int UseAddGramSch; 407 408 int Seed; 408 409 409 410 int MaxOuterStep; 410 411 int OutVisStep; … … 414 415 int MaxPsiStep; 415 416 double EpsWannier; 416 417 417 418 int MaxMinStep; 418 419 double RelEpsTotalEnergy; … … 423 424 double InitRelEpsKineticEnergy; 424 425 int InitMaxMinGapStopStep; 425 426 426 427 //double BoxLength[NDIM*NDIM]; 427 428 428 429 double ECut; 429 430 int MaxLevel; … … 434 435 int RTActualUse; 435 436 int AddPsis; 436 437 437 438 double RCut; 438 439 int StructOpt; … … 441 442 int MaxTypes; 442 443 443 444 444 445 int ParseForParameter(int verbose, ifstream *file, const char *name, int sequential, int const xth, int const yth, int type, void *value, int repetition, int critical); 445 446 446 447 public: 447 448 config(); -
src/vector.cpp
r1ffa21 r69eb71 1 1 /** \file vector.cpp 2 * 2 * 3 3 * Function implementations for the class vector. 4 * 5 */ 6 4 * 5 */ 6 7 7 #include "molecules.hpp" 8 8 9 9 10 10 /************************************ Functions for class vector ************************************/ … … 31 31 for (int i=NDIM;i--;) 32 32 res += (x[i]-y->x[i])*(x[i]-y->x[i]); 33 return (res); 33 return (res); 34 34 }; 35 35 … … 69 69 if (tmp < res) res = tmp; 70 70 } 71 return (res); 71 return (res); 72 72 }; 73 73 … … 112 112 for (int i=NDIM;i--;) 113 113 res += x[i]*y->x[i]; 114 return (res); 114 return (res); 115 115 }; 116 116 … … 121 121 * \param *y array to vector with which to calculate crossproduct 122 122 * \return \f$ x \times y \f& 123 */ 123 */ 124 124 void Vector::VectorProduct(const Vector *y) 125 125 { 126 126 Vector tmp; 127 tmp [0] = x[1]*y->x[2] - x[2]*y->x[1];128 tmp [1] = x[2]*y->x[0] - x[0]*y->x[2];129 tmp [2] = x[0]*y->x[1] - x[1]*Y->x[0];127 tmp.x[0] = x[1]* (y->x[2]) - x[2]* (y->x[1]); 128 tmp.x[1] = x[2]* (y->x[0]) - x[0]* (y->x[2]); 129 tmp.x[2] = x[0]* (y->x[1]) - x[1]* (y->x[0]); 130 130 this->CopyVector(&tmp); 131 131 … … 134 134 135 135 /** projects this vector onto plane defined by \a *y. 136 * \param *y array tonormal vector of plane136 * \param *y normal vector of plane 137 137 * \return \f$\langle x, y \rangle\f$ 138 138 */ … … 141 141 Vector tmp; 142 142 tmp.CopyVector(y); 143 tmp.Scale(Projection(y)); 143 tmp.Normalize(); 144 tmp.Scale(ScalarProduct(&tmp)); 144 145 this->SubtractVector(&tmp); 145 146 }; … … 162 163 for (int i=NDIM;i--;) 163 164 res += this->x[i]*this->x[i]; 164 return (sqrt(res)); 165 return (sqrt(res)); 165 166 }; 166 167 … … 196 197 */ 197 198 void Vector::Init(double x1, double x2, double x3) 198 { 199 { 199 200 x[0] = x1; 200 201 x[1] = x2; … … 202 203 }; 203 204 204 /** Calculates the angle between this and another vector. 205 /** Calculates the angle between this and another vector. 205 206 * \param *y array to second vector 206 207 * \return \f$\acos\bigl(frac{\langle x, y \rangle}{|x||y|}\bigr)\f$ … … 208 209 double Vector::Angle(Vector *y) const 209 210 { 210 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 211 return acos(this->ScalarProduct(y)/Norm()/y->Norm()); 211 212 }; 212 213 … … 256 257 257 258 /** Sums two vectors \a and \b component-wise. 258 * \param a first vector 259 * \param a first vector 259 260 * \param b second vector 260 261 * \return a + b … … 269 270 270 271 /** Factors given vector \a a times \a m. 271 * \param a vector 272 * \param a vector 272 273 * \param m factor 273 274 * \return a + b … … 327 328 }; 328 329 329 /** Translate atom by given vector. 330 /** Translate atom by given vector. 330 331 * \param trans[] translation vector. 331 332 */ … … 334 335 for (int i=NDIM;i--;) 335 336 x[i] += trans->x[i]; 336 }; 337 }; 337 338 338 339 /** Do a matrix multiplication. … … 373 374 B[7] = -detAReci*RDET2(A[0],A[1],A[6],A[7]); // A_32 374 375 B[8] = detAReci*RDET2(A[0],A[1],A[3],A[4]); // A_33 375 376 376 377 // do the matrix multiplication 377 378 C.x[0] = B[0]*x[0]+B[3]*x[1]+B[6]*x[2]; … … 397 398 { 398 399 for(int i=NDIM;i--;) 399 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 400 }; 401 402 /** Mirrors atom against a given plane. 400 x[i] = factors[0]*x1->x[i] + factors[1]*x2->x[i] + factors[2]*x3->x[i]; 401 }; 402 403 /** Mirrors atom against a given plane. 403 404 * \param n[] normal vector of mirror plane. 404 405 */ … … 416 417 Output((ofstream *)&cout); 417 418 cout << endl; 418 }; 419 }; 419 420 420 421 /** Calculates normal vector for three given vectors (being three points in space). … … 448 449 this->x[2] = (x1.x[0]*x2.x[1] - x1.x[1]*x2.x[0]); 449 450 Normalize(); 450 451 451 452 return true; 452 453 }; … … 506 507 /** Creates this vector as one of the possible orthonormal ones to the given one. 507 508 * Just scan how many components of given *vector are unequal to zero and 508 * try to get the skp of both to be zero accordingly. 509 * try to get the skp of both to be zero accordingly. 509 510 * \param *vector given vector 510 511 * \return true - success, false - failure (null vector given) … … 527 528 Components[Last++] = j; 528 529 cout << Verbose(4) << Last << " Components != 0: (" << Components[0] << "," << Components[1] << "," << Components[2] << ")" << endl; 529 530 530 531 switch(Last) { 531 532 case 3: // threecomponent system … … 540 541 case 1: // one component system 541 542 // set sole non-zero component to 0, and one of the other zero component pendants to 1 542 x[(Components[0]+2)%NDIM] = 0.; 543 x[(Components[0]+1)%NDIM] = 1.; 544 x[Components[0]] = 0.; 543 x[(Components[0]+2)%NDIM] = 0.; 544 x[(Components[0]+1)%NDIM] = 1.; 545 x[Components[0]] = 0.; 545 546 return true; 546 547 break; … … 559 560 { 560 561 // cout << Verbose(3) << "For comparison: "; 561 // cout << "A " << A->Projection(this) << "\t"; 562 // cout << "B " << B->Projection(this) << "\t"; 563 // cout << "C " << C->Projection(this) << "\t"; 562 // cout << "A " << A->Projection(this) << "\t"; 563 // cout << "B " << B->Projection(this) << "\t"; 564 // cout << "C " << C->Projection(this) << "\t"; 564 565 // cout << endl; 565 566 return A->Projection(this); … … 571 572 * \return true if success, false if failed due to linear dependency 572 573 */ 573 bool Vector::LSQdistance(Vector **vectors, int num) 574 bool Vector::LSQdistance(Vector **vectors, int num) 574 575 { 575 576 int j; 576 577 577 578 for (j=0;j<num;j++) { 578 579 cout << Verbose(1) << j << "th atom's vector: "; … … 583 584 int np = 3; 584 585 struct LSQ_params par; 585 586 586 587 const gsl_multimin_fminimizer_type *T = 587 588 gsl_multimin_fminimizer_nmsimplex; … … 589 590 gsl_vector *ss, *y; 590 591 gsl_multimin_function minex_func; 591 592 592 593 size_t iter = 0, i; 593 594 int status; 594 595 double size; 595 596 596 597 /* Initial vertex size vector */ 597 598 ss = gsl_vector_alloc (np); 598 599 y = gsl_vector_alloc (np); 599 600 600 601 /* Set all step sizes to 1 */ 601 602 gsl_vector_set_all (ss, 1.0); 602 603 603 604 /* Starting point */ 604 605 par.vectors = vectors; 605 606 par.num = num; 606 607 607 608 for (i=NDIM;i--;) 608 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 609 609 gsl_vector_set(y, i, (vectors[0]->x[i] - vectors[1]->x[i])/2.); 610 610 611 /* Initialize method and iterate */ 611 612 minex_func.f = &LSQ; 612 613 minex_func.n = np; 613 614 minex_func.params = (void *)∥ 614 615 615 616 s = gsl_multimin_fminimizer_alloc (T, np); 616 617 gsl_multimin_fminimizer_set (s, &minex_func, y, ss); 617 618 618 619 do 619 620 { 620 621 iter++; 621 622 status = gsl_multimin_fminimizer_iterate(s); 622 623 623 624 if (status) 624 625 break; 625 626 626 627 size = gsl_multimin_fminimizer_size (s); 627 628 status = gsl_multimin_test_size (size, 1e-2); 628 629 629 630 if (status == GSL_SUCCESS) 630 631 { 631 632 printf ("converged to minimum at\n"); 632 633 } 633 634 634 635 printf ("%5d ", (int)iter); 635 636 for (i = 0; i < (size_t)np; i++) … … 640 641 } 641 642 while (status == GSL_CONTINUE && iter < 100); 642 643 643 644 for (i=(size_t)np;i--;) 644 645 this->x[i] = gsl_vector_get(s->x, i); … … 706 707 * \param alpha first angle 707 708 * \param beta second angle 708 * \param c norm of final vector 709 * \param c norm of final vector 709 710 * \return a vector with \f$\langle x1,x2 \rangle=A\f$, \f$\langle x1,y \rangle = B\f$ and with norm \a c. 710 * \bug this is not yet working properly 711 * \bug this is not yet working properly 711 712 */ 712 713 bool Vector::SolveSystem(Vector *x1, Vector *x2, Vector *y, double alpha, double beta, double c) … … 724 725 if (fabs(x1->x[0]) < MYEPSILON) { // check for zero components for the later flipping and back-flipping 725 726 if (fabs(x1->x[1]) > MYEPSILON) { 726 flag = 1; 727 flag = 1; 727 728 } else if (fabs(x1->x[2]) > MYEPSILON) { 728 729 flag = 2; … … 757 758 // now comes the case system 758 759 D1 = -y->x[0]/x1->x[0]*x1->x[1]+y->x[1]; 759 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 760 D2 = -y->x[0]/x1->x[0]*x1->x[2]+y->x[2]; 760 761 D3 = y->x[0]/x1->x[0]*A-B1; 761 762 cout << Verbose(2) << "D1 " << D1 << "\tD2 " << D2 << "\tD3 " << D3 << "\n"; 762 763 if (fabs(D1) < MYEPSILON) { 763 cout << Verbose(2) << "D1 == 0!\n"; 764 cout << Verbose(2) << "D1 == 0!\n"; 764 765 if (fabs(D2) > MYEPSILON) { 765 cout << Verbose(3) << "D2 != 0!\n"; 766 cout << Verbose(3) << "D2 != 0!\n"; 766 767 x[2] = -D3/D2; 767 768 E1 = A/x1->x[0] + x1->x[2]/x1->x[0]*D3/D2; … … 773 774 cout << Verbose(3) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 774 775 if (fabs(F1) < MYEPSILON) { 775 cout << Verbose(4) << "F1 == 0!\n"; 776 cout << Verbose(4) << "F1 == 0!\n"; 776 777 cout << Verbose(4) << "Gleichungssystem linear\n"; 777 x[1] = F3/(2.*F2); 778 x[1] = F3/(2.*F2); 778 779 } else { 779 780 p = F2/F1; 780 781 q = p*p - F3/F1; 781 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 782 cout << Verbose(4) << "p " << p << "\tq " << q << endl; 782 783 if (q < 0) { 783 784 cout << Verbose(4) << "q < 0" << endl; … … 800 801 cout << Verbose(2) << "F1 " << F1 << "\tF2 " << F2 << "\tF3 " << F3 << "\n"; 801 802 if (fabs(F1) < MYEPSILON) { 802 cout << Verbose(3) << "F1 == 0!\n"; 803 cout << Verbose(3) << "F1 == 0!\n"; 803 804 cout << Verbose(3) << "Gleichungssystem linear\n"; 804 x[2] = F3/(2.*F2); 805 x[2] = F3/(2.*F2); 805 806 } else { 806 807 p = F2/F1; 807 808 q = p*p - F3/F1; 808 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 809 cout << Verbose(3) << "p " << p << "\tq " << q << endl; 809 810 if (q < 0) { 810 811 cout << Verbose(3) << "q < 0" << endl; … … 850 851 } 851 852 cout << Verbose(2) << i << ": sign matrix is " << sign[0] << "\t" << sign[1] << "\t" << sign[2] << "\n"; 852 // apply sign matrix 853 // apply sign matrix 853 854 for (j=NDIM;j--;) 854 855 x[j] *= sign[j]; … … 856 857 ang = x2->Angle (this); 857 858 cout << Verbose(1) << i << "th angle " << ang << "\tbeta " << cos(beta) << " :\t"; 858 if (fabs(ang - cos(beta)) < MYEPSILON) { 859 if (fabs(ang - cos(beta)) < MYEPSILON) { 859 860 break; 860 861 }
Note:
See TracChangeset
for help on using the changeset viewer.