Changes in src/molecules.cpp [4158ba:cc2ee5]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/molecules.cpp
-
Property mode
changed from
100644
to100755
r4158ba rcc2ee5 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 220 220 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 221 221 if (BondRescale == -1) { 222 cerr << Verbose(3) << "WARNING: There is no typical bond distance for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 BondRescale = bondlength; 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 return false; 224 BondRescale = bondlength; 224 225 } else { 225 226 if (!IsAngstroem) … … 272 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 273 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; 274 275 275 276 // determine the plane of these two with the *origin 276 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 285 286 Orthovector1.Normalize(); 286 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 287 288 288 289 // create the two Hydrogens ... 289 290 FirstOtherAtom = new atom(); … … 299 300 bondangle = TopOrigin->type->HBondAngle[1]; 300 301 if (bondangle == -1) { 301 *out << Verbose(3) << "WARNING: There is no typical bond angle for bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 302 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 303 return false; 302 304 bondangle = 0; 303 305 } … … 316 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 317 319 } 318 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 319 321 SecondOtherAtom->x.Scale(&BondRescale); 320 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 321 323 for(int i=NDIM;i--;) { // and make relative to origin atom 322 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 323 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 326 } … … 363 365 // *out << endl; 364 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 365 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 366 368 // Orthovector2.Output(out); 367 369 // *out << endl; 368 370 369 371 // create correct coordination for the three atoms 370 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 378 380 factors[0] = d; 379 381 factors[1] = f; 380 factors[2] = 0.; 382 factors[2] = 0.; 381 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 382 384 factors[1] = -0.5*f; 383 factors[2] = g; 385 factors[2] = g; 384 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 385 factors[2] = -g; 387 factors[2] = -g; 386 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 389 … … 435 437 */ 436 438 bool molecule::AddXYZFile(string filename) 437 { 439 { 438 440 istringstream *input = NULL; 439 441 int NumberOfAtoms = 0; // atom number in xyz read … … 444 446 string line; // currently parsed line 445 447 double x[3]; // atom coordinates 446 448 447 449 xyzfile.open(filename.c_str()); 448 450 if (!xyzfile) … … 452 454 input = new istringstream(line); 453 455 *input >> NumberOfAtoms; 454 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 455 457 getline(xyzfile,line,'\n'); // Read comment 456 458 cout << Verbose(1) << "Comment: " << line << endl; 457 459 458 460 if (MDSteps == 0) // no atoms yet present 459 461 MDSteps++; … … 489 491 xyzfile.close(); 490 492 delete(input); 491 return true; 493 return true; 492 494 }; 493 495 … … 501 503 atom *LeftAtom = NULL, *RightAtom = NULL; 502 504 atom *Walker = NULL; 503 505 504 506 // copy all atoms 505 507 Walker = start; … … 508 510 CurrentAtom = copy->AddCopyAtom(Walker); 509 511 } 510 512 511 513 // copy all bonds 512 514 bond *Binder = first; … … 532 534 copy->NoCyclicBonds++; 533 535 NewBond->Type = Binder->Type; 534 } 536 } 535 537 // correct fathers 536 538 Walker = copy->start; … … 549 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 550 552 } 551 553 552 554 return copy; 553 555 }; … … 574 576 575 577 /** Remove bond from bond chain list. 576 * \todo Function not implemented yet 578 * \todo Function not implemented yet 577 579 * \param *pointer bond pointer 578 580 * \return true - bound found and removed, false - bond not found/removed … … 586 588 587 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 588 * \todo Function not implemented yet 590 * \todo Function not implemented yet 589 591 * \param *BondPartner atom to be removed 590 592 * \return true - bounds found and removed, false - bonds not found/removed … … 619 621 Vector *min = new Vector; 620 622 Vector *max = new Vector; 621 623 622 624 // gather min and max for each axis 623 625 ptr = start->next; // start at first in list … … 665 667 { 666 668 Vector *min = new Vector; 667 669 668 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 669 671 atom *ptr = start->next; // start at first in list … … 681 683 } 682 684 } 683 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 684 686 // max->Output(out); 685 687 // *out << ", Minimum is "; … … 689 691 max->AddVector(min); 690 692 Translate(min); 691 } 693 } 692 694 delete(min); 693 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 694 }; 696 }; 695 697 696 698 /** Centers the center of the atoms at (0,0,0). … … 702 704 int Num = 0; 703 705 atom *ptr = start->next; // start at first in list 704 706 705 707 for(int i=NDIM;i--;) // zero center vector 706 708 center->x[i] = 0.; 707 709 708 710 if (ptr != end) { //list not empty? 709 711 while (ptr->next != end) { // continue with second if present 710 712 ptr = ptr->next; 711 713 Num++; 712 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 713 715 } 714 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 715 717 Translate(center); 716 718 } 717 }; 719 }; 718 720 719 721 /** Returns vector pointing to center of gravity. … … 727 729 Vector tmp; 728 730 double Num = 0; 729 731 730 732 a->Zero(); 731 733 … … 735 737 Num += 1.; 736 738 tmp.CopyVector(&ptr->x); 737 a->AddVector(&tmp); 739 a->AddVector(&tmp); 738 740 } 739 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 755 757 Vector tmp; 756 758 double Num = 0; 757 759 758 760 a->Zero(); 759 761 … … 764 766 tmp.CopyVector(&ptr->x); 765 767 tmp.Scale(ptr->type->mass); // scale by mass 766 a->AddVector(&tmp); 768 a->AddVector(&tmp); 767 769 } 768 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 787 789 Translate(center); 788 790 } 789 }; 791 }; 790 792 791 793 /** Scales all atoms by \a *factor. … … 801 803 Trajectories[ptr].R.at(j).Scale(factor); 802 804 ptr->x.Scale(factor); 803 } 804 }; 805 806 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 807 809 * \param trans[] translation vector. 808 810 */ … … 816 818 Trajectories[ptr].R.at(j).Translate(trans); 817 819 ptr->x.Translate(trans); 818 } 819 }; 820 821 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 822 824 * \param n[] normal vector of mirror plane. 823 825 */ … … 831 833 Trajectories[ptr].R.at(j).Mirror(n); 832 834 ptr->x.Mirror(n); 833 } 835 } 834 836 }; 835 837 … … 845 847 bool flag; 846 848 Vector Testvector, Translationvector; 847 849 848 850 do { 849 851 Center.Zero(); … … 861 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 862 864 for (int j=0;j<NDIM;j++) { 863 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 864 866 if ((fabs(tmp)) > BondDistance) { 865 867 flag = false; … … 877 879 cout << Verbose(1) << "vector is: "; 878 880 Testvector.Output((ofstream *)&cout); 879 cout << endl; 881 cout << endl; 880 882 #ifdef ADDHYDROGEN 881 883 // now also change all hydrogens … … 890 892 cout << Verbose(1) << "Hydrogen vector is: "; 891 893 Testvector.Output((ofstream *)&cout); 892 cout << endl; 894 cout << endl; 893 895 } 894 896 } … … 912 914 913 915 CenterGravity(out, CenterOfGravity); 914 915 // reset inertia tensor 916 917 // reset inertia tensor 916 918 for(int i=0;i<NDIM*NDIM;i++) 917 919 InertiaTensor[i] = 0.; 918 920 919 921 // sum up inertia tensor 920 922 while (ptr->next != end) { … … 941 943 } 942 944 *out << endl; 943 945 944 946 // diagonalize to determine principal axis system 945 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 950 952 gsl_eigen_symmv_free(T); 951 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 952 954 953 955 for(int i=0;i<NDIM;i++) { 954 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 955 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 956 958 } 957 959 958 960 // check whether we rotate or not 959 961 if (DoRotate) { 960 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 961 963 // the eigenvectors specify the transformation matrix 962 964 ptr = start; … … 970 972 971 973 // summing anew for debugging (resulting matrix has to be diagonal!) 972 // reset inertia tensor 974 // reset inertia tensor 973 975 for(int i=0;i<NDIM*NDIM;i++) 974 976 InertiaTensor[i] = 0.; 975 977 976 978 // sum up inertia tensor 977 979 ptr = start; … … 1000 1002 *out << endl; 1001 1003 } 1002 1004 1003 1005 // free everything 1004 1006 delete(CenterOfGravity); … … 1007 1009 }; 1008 1010 1009 /** Evaluates the potential energy used for constrained molecular dynamics.1010 * \f$V_i^{con} = c^{bond} \cdot | r_{P(i)} - R_i | + sum_{i \neq j} C^{min} \cdot \frac{1}{C_{ij}} + C^{inj} \Bigl (1 - \theta \bigl (\prod_{i \neq j} (P(i) - P(j)) \bigr ) \Bigr )\f$1011 * where the first term points to the target in minimum distance, the second is a penalty for trajectories lying too close to each other (\f$C_{ij}$ is minimum distance between1012 * trajectories i and j) and the third term is a penalty for two atoms trying to each the same target point.1013 * Note that for the second term we have to solve the following linear system:1014 * \f$-c_1 \cdot n_1 + c_2 \cdot n_2 + C \cdot n_3 = - p_2 + p_1\f$, where \f$c_1\f$, \f$c_2\f$ and \f$C\f$ are constants,1015 * offset vector \f$p_1\f$ in direction \f$n_1\f$, offset vector \f$p_2\f$ in direction \f$n_2\f$,1016 * \f$n_3\f$ is the normal vector to both directions. \f$C\f$ would be the minimum distance between the two lines.1017 * \sa molecule::MinimiseConstrainedPotential(), molecule::VerletForceIntegration()1018 * \param *out output stream for debugging1019 * \param *PermutationMap gives target ptr for each atom, array of size molecule::AtomCount (this is "x" in \f$V^{con}(x)\f$)1020 * \param startstep start configuration (MDStep in molecule::trajectories)1021 * \param endstep end configuration (MDStep in molecule::trajectories)1022 * \param *constants constant in front of each term1023 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)1024 * \return potential energy1025 * \note This routine is scaling quadratically which is not optimal.1026 * \todo There's a bit double counting going on for the first time, bu nothing to worry really about.1027 */1028 double molecule::ConstrainedPotential(ofstream *out, atom **PermutationMap, int startstep, int endstep, double *constants, bool IsAngstroem)1029 {1030 double result = 0., tmp, Norm1, Norm2;1031 atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;1032 Vector trajectory1, trajectory2, normal, TestVector;1033 gsl_matrix *A = gsl_matrix_alloc(NDIM,NDIM);1034 gsl_vector *x = gsl_vector_alloc(NDIM);1035 1036 // go through every atom1037 Walker = start;1038 while (Walker->next != end) {1039 Walker = Walker->next;1040 // first term: distance to target1041 Runner = PermutationMap[Walker->nr]; // find target point1042 tmp = (Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)));1043 tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;1044 result += constants[0] * tmp;1045 //*out << Verbose(4) << "Adding " << tmp*constants[0] << "." << endl;1046 1047 // second term: sum of distances to other trajectories1048 Runner = start;1049 while (Runner->next != end) {1050 Runner = Runner->next;1051 if (Runner == Walker) // hence, we only go up to the Walker, not beyond (similar to i=0; i<j; i++)1052 break;1053 // determine normalized trajectories direction vector (n1, n2)1054 Sprinter = PermutationMap[Walker->nr]; // find first target point1055 trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep));1056 trajectory1.SubtractVector(&Trajectories[Walker].R.at(startstep));1057 trajectory1.Normalize();1058 Norm1 = trajectory1.Norm();1059 Sprinter = PermutationMap[Runner->nr]; // find second target point1060 trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep));1061 trajectory2.SubtractVector(&Trajectories[Runner].R.at(startstep));1062 trajectory2.Normalize();1063 Norm2 = trajectory1.Norm();1064 // check whether either is zero()1065 if ((Norm1 < MYEPSILON) && (Norm2 < MYEPSILON)) {1066 tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));1067 } else if (Norm1 < MYEPSILON) {1068 Sprinter = PermutationMap[Walker->nr]; // find first target point1069 trajectory1.CopyVector(&Trajectories[Sprinter].R.at(endstep)); // copy first offset1070 trajectory1.SubtractVector(&Trajectories[Runner].R.at(startstep)); // subtract second offset1071 trajectory2.Scale( trajectory1.ScalarProduct(&trajectory2) ); // trajectory2 is scaled to unity, hence we don't need to divide by anything1072 trajectory1.SubtractVector(&trajectory2); // project the part in norm direction away1073 tmp = trajectory1.Norm(); // remaining norm is distance1074 } else if (Norm2 < MYEPSILON) {1075 Sprinter = PermutationMap[Runner->nr]; // find second target point1076 trajectory2.CopyVector(&Trajectories[Sprinter].R.at(endstep)); // copy second offset1077 trajectory2.SubtractVector(&Trajectories[Walker].R.at(startstep)); // subtract first offset1078 trajectory1.Scale( trajectory2.ScalarProduct(&trajectory1) ); // trajectory1 is scaled to unity, hence we don't need to divide by anything1079 trajectory2.SubtractVector(&trajectory1); // project the part in norm direction away1080 tmp = trajectory2.Norm(); // remaining norm is distance1081 } else if ((fabs(trajectory1.ScalarProduct(&trajectory2)/Norm1/Norm2) - 1.) < MYEPSILON) { // check whether they're linear dependent1082 // *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear dependent: ";1083 // *out << trajectory1;1084 // *out << " and ";1085 // *out << trajectory2;1086 tmp = Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(startstep));1087 // *out << " with distance " << tmp << "." << endl;1088 } else { // determine distance by finding minimum distance1089 // *out << Verbose(3) << "Both trajectories of " << *Walker << " and " << *Runner << " are linear independent ";1090 // *out << endl;1091 // *out << "First Trajectory: ";1092 // *out << trajectory1 << endl;1093 // *out << "Second Trajectory: ";1094 // *out << trajectory2 << endl;1095 // determine normal vector for both1096 normal.MakeNormalVector(&trajectory1, &trajectory2);1097 // print all vectors for debugging1098 // *out << "Normal vector in between: ";1099 // *out << normal << endl;1100 // setup matrix1101 for (int i=NDIM;i--;) {1102 gsl_matrix_set(A, 0, i, trajectory1.x[i]);1103 gsl_matrix_set(A, 1, i, trajectory2.x[i]);1104 gsl_matrix_set(A, 2, i, normal.x[i]);1105 gsl_vector_set(x,i, (Trajectories[Walker].R.at(startstep).x[i] - Trajectories[Runner].R.at(startstep).x[i]));1106 }1107 // solve the linear system by Householder transformations1108 gsl_linalg_HH_svx(A, x);1109 // distance from last component1110 tmp = gsl_vector_get(x,2);1111 // *out << " with distance " << tmp << "." << endl;1112 // test whether we really have the intersection (by checking on c_1 and c_2)1113 TestVector.CopyVector(&Trajectories[Runner].R.at(startstep));1114 trajectory2.Scale(gsl_vector_get(x,1));1115 TestVector.AddVector(&trajectory2);1116 normal.Scale(gsl_vector_get(x,2));1117 TestVector.AddVector(&normal);1118 TestVector.SubtractVector(&Trajectories[Walker].R.at(startstep));1119 trajectory1.Scale(gsl_vector_get(x,0));1120 TestVector.SubtractVector(&trajectory1);1121 if (TestVector.Norm() < MYEPSILON) {1122 // *out << Verbose(2) << "Test: ok.\tDistance of " << tmp << " is correct." << endl;1123 } else {1124 // *out << Verbose(2) << "Test: failed.\tIntersection is off by ";1125 // *out << TestVector;1126 // *out << "." << endl;1127 }1128 }1129 // add up1130 tmp *= IsAngstroem ? 1. : 1./AtomicLengthToAngstroem;1131 if (fabs(tmp) > MYEPSILON) {1132 result += constants[1] * 1./tmp;1133 //*out << Verbose(4) << "Adding " << 1./tmp*constants[1] << "." << endl;1134 }1135 }1136 1137 // third term: penalty for equal targets1138 Runner = start;1139 while (Runner->next != end) {1140 Runner = Runner->next;1141 if ((PermutationMap[Walker->nr] == PermutationMap[Runner->nr]) && (Walker->nr < Runner->nr)) {1142 Sprinter = PermutationMap[Walker->nr];1143 // *out << *Walker << " and " << *Runner << " are heading to the same target at ";1144 // *out << Trajectories[Sprinter].R.at(endstep);1145 // *out << ", penalting." << endl;1146 result += constants[2];1147 //*out << Verbose(4) << "Adding " << constants[2] << "." << endl;1148 }1149 }1150 }1151 1152 return result;1153 };1154 1155 void PrintPermutationMap(ofstream *out, atom **PermutationMap, int Nr)1156 {1157 stringstream zeile1, zeile2;1158 int *DoubleList = (int *) Malloc(Nr*sizeof(int), "PrintPermutationMap: *DoubleList");1159 int doubles = 0;1160 for (int i=0;i<Nr;i++)1161 DoubleList[i] = 0;1162 zeile1 << "PermutationMap: ";1163 zeile2 << " ";1164 for (int i=0;i<Nr;i++) {1165 DoubleList[PermutationMap[i]->nr]++;1166 zeile1 << i << " ";1167 zeile2 << PermutationMap[i]->nr << " ";1168 }1169 for (int i=0;i<Nr;i++)1170 if (DoubleList[i] > 1)1171 doubles++;1172 // *out << "Found " << doubles << " Doubles." << endl;1173 Free((void **)&DoubleList, "PrintPermutationMap: *DoubleList");1174 // *out << zeile1.str() << endl << zeile2.str() << endl;1175 };1176 1177 /** Minimises the extra potential for constrained molecular dynamics and gives forces and the constrained potential energy.1178 * We do the following:1179 * -# Generate a distance list from all source to all target points1180 * -# Sort this per source point1181 * -# Take for each source point the target point with minimum distance, use this as initial permutation1182 * -# check whether molecule::ConstrainedPotential() is greater than injective penalty1183 * -# If so, we go through each source point, stepping down in the sorted target point distance list and re-checking potential.1184 * -# Next, we only apply transformations that keep the injectivity of the permutations list.1185 * -# Hence, for one source point we step down the ladder and seek the corresponding owner of this new target1186 * point and try to change it for one with lesser distance, or for the next one with greater distance, but only1187 * if this decreases the conditional potential.1188 * -# finished.1189 * -# Then, we calculate the forces by taking the spatial derivative, where we scale the potential to such a degree,1190 * that the total force is always pointing in direction of the constraint force (ensuring that we move in the1191 * right direction).1192 * -# Finally, we calculate the potential energy and return.1193 * \param *out output stream for debugging1194 * \param **PermutationMap on return: mapping between the atom label of the initial and the final configuration1195 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)1196 * \param endstep step giving final position in constrained MD1197 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false)1198 * \sa molecule::VerletForceIntegration()1199 * \return potential energy (and allocated **PermutationMap (array of molecule::AtomCount ^2)1200 * \todo The constrained potential's constants are set to fixed values right now, but they should scale based on checks of the system in order1201 * to ensure they're properties (e.g. constants[2] always greater than the energy of the system).1202 * \bug this all is not O(N log N) but O(N^2)1203 */1204 double molecule::MinimiseConstrainedPotential(ofstream *out, atom **&PermutationMap, int startstep, int endstep, bool IsAngstroem)1205 {1206 double Potential, OldPotential, OlderPotential;1207 PermutationMap = (atom **) Malloc(AtomCount*sizeof(atom *), "molecule::MinimiseConstrainedPotential: **PermutationMap");1208 DistanceMap **DistanceList = (DistanceMap **) Malloc(AtomCount*sizeof(DistanceMap *), "molecule::MinimiseConstrainedPotential: **DistanceList");1209 DistanceMap::iterator *DistanceIterators = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *DistanceIterators");1210 int *DoubleList = (int *) Malloc(AtomCount*sizeof(int), "molecule::MinimiseConstrainedPotential: *DoubleList");1211 DistanceMap::iterator *StepList = (DistanceMap::iterator *) Malloc(AtomCount*sizeof(DistanceMap::iterator), "molecule::MinimiseConstrainedPotential: *StepList");1212 double constants[3];1213 int round;1214 atom *Walker = NULL, *Runner = NULL, *Sprinter = NULL;1215 DistanceMap::iterator Rider, Strider;1216 1217 /// Minimise the potential1218 // set Lagrange multiplier constants1219 constants[0] = 10.;1220 constants[1] = 1.;1221 constants[2] = 1e+7; // just a huge penalty1222 // generate the distance list1223 *out << Verbose(1) << "Creating the distance list ... " << endl;1224 for (int i=AtomCount; i--;) {1225 DoubleList[i] = 0; // stores for how many atoms in startstep this atom is a target in endstep1226 DistanceList[i] = new DistanceMap; // is the distance sorted target list per atom1227 DistanceList[i]->clear();1228 }1229 *out << Verbose(1) << "Filling the distance list ... " << endl;1230 Walker = start;1231 while (Walker->next != end) {1232 Walker = Walker->next;1233 Runner = start;1234 while(Runner->next != end) {1235 Runner = Runner->next;1236 DistanceList[Walker->nr]->insert( DistancePair(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Runner].R.at(endstep)), Runner) );1237 }1238 }1239 // create the initial PermutationMap (source -> target)1240 Walker = start;1241 while (Walker->next != end) {1242 Walker = Walker->next;1243 StepList[Walker->nr] = DistanceList[Walker->nr]->begin(); // stores the step to the next iterator that could be a possible next target1244 PermutationMap[Walker->nr] = DistanceList[Walker->nr]->begin()->second; // always pick target with the smallest distance1245 DoubleList[DistanceList[Walker->nr]->begin()->second->nr]++; // increase this target's source count (>1? not injective)1246 DistanceIterators[Walker->nr] = DistanceList[Walker->nr]->begin(); // and remember which one we picked1247 *out << *Walker << " starts with distance " << DistanceList[Walker->nr]->begin()->first << "." << endl;1248 }1249 *out << Verbose(1) << "done." << endl;1250 // make the PermutationMap injective by checking whether we have a non-zero constants[2] term in it1251 *out << Verbose(1) << "Making the PermutationMap injective ... " << endl;1252 Walker = start;1253 DistanceMap::iterator NewBase;1254 OldPotential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));1255 while ((OldPotential) > constants[2]) {1256 PrintPermutationMap(out, PermutationMap, AtomCount);1257 Walker = Walker->next;1258 if (Walker == end) // round-robin at the end1259 Walker = start->next;1260 if (DoubleList[DistanceIterators[Walker->nr]->second->nr] <= 1) // no need to make those injective that aren't1261 continue;1262 // now, try finding a new one1263 NewBase = DistanceIterators[Walker->nr]; // store old base1264 do {1265 NewBase++; // take next further distance in distance to targets list that's a target of no one1266 } while ((DoubleList[NewBase->second->nr] != 0) && (NewBase != DistanceList[Walker->nr]->end()));1267 if (NewBase != DistanceList[Walker->nr]->end()) {1268 PermutationMap[Walker->nr] = NewBase->second;1269 Potential = fabs(ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem));1270 if (Potential > OldPotential) { // undo1271 PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;1272 } else { // do1273 DoubleList[DistanceIterators[Walker->nr]->second->nr]--; // decrease the old entry in the doubles list1274 DoubleList[NewBase->second->nr]++; // increase the old entry in the doubles list1275 DistanceIterators[Walker->nr] = NewBase;1276 OldPotential = Potential;1277 *out << Verbose(3) << "Found a new permutation, new potential is " << OldPotential << "." << endl;1278 }1279 }1280 }1281 for (int i=AtomCount; i--;) // now each single entry in the DoubleList should be <=11282 if (DoubleList[i] > 1) {1283 cerr << "Failed to create an injective PermutationMap!" << endl;1284 exit(1);1285 }1286 *out << Verbose(1) << "done." << endl;1287 Free((void **)&DoubleList, "molecule::MinimiseConstrainedPotential: *DoubleList");1288 // argument minimise the constrained potential in this injective PermutationMap1289 *out << Verbose(1) << "Argument minimising the PermutationMap, at current potential " << OldPotential << " ... " << endl;1290 OldPotential = 1e+10;1291 round = 0;1292 do {1293 *out << "Starting round " << ++round << " ... " << endl;1294 OlderPotential = OldPotential;1295 do {1296 Walker = start;1297 while (Walker->next != end) { // pick one1298 Walker = Walker->next;1299 PrintPermutationMap(out, PermutationMap, AtomCount);1300 Sprinter = DistanceIterators[Walker->nr]->second; // store initial partner1301 Strider = DistanceIterators[Walker->nr]; //remember old iterator1302 DistanceIterators[Walker->nr] = StepList[Walker->nr];1303 if (DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->end()) {// stop, before we run through the list and still on1304 DistanceIterators[Walker->nr] == DistanceList[Walker->nr]->begin();1305 break;1306 }1307 //*out << Verbose(2) << "Current Walker: " << *Walker << " with old/next candidate " << *Sprinter << "/" << *DistanceIterators[Walker->nr]->second << "." << endl;1308 // find source of the new target1309 Runner = start->next;1310 while(Runner != end) { // find the source whose toes we might be stepping on (Walker's new target should be in use by another already)1311 if (PermutationMap[Runner->nr] == DistanceIterators[Walker->nr]->second) {1312 //*out << Verbose(2) << "Found the corresponding owner " << *Runner << " to " << *PermutationMap[Runner->nr] << "." << endl;1313 break;1314 }1315 Runner = Runner->next;1316 }1317 if (Runner != end) { // we found the other source1318 // then look in its distance list for Sprinter1319 Rider = DistanceList[Runner->nr]->begin();1320 for (; Rider != DistanceList[Runner->nr]->end(); Rider++)1321 if (Rider->second == Sprinter)1322 break;1323 if (Rider != DistanceList[Runner->nr]->end()) { // if we have found one1324 //*out << Verbose(2) << "Current Other: " << *Runner << " with old/next candidate " << *PermutationMap[Runner->nr] << "/" << *Rider->second << "." << endl;1325 // exchange both1326 PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // put next farther distance into PermutationMap1327 PermutationMap[Runner->nr] = Sprinter; // and hand the old target to its respective owner1328 PrintPermutationMap(out, PermutationMap, AtomCount);1329 // calculate the new potential1330 //*out << Verbose(2) << "Checking new potential ..." << endl;1331 Potential = ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);1332 if (Potential > OldPotential) { // we made everything worse! Undo ...1333 //*out << Verbose(3) << "Nay, made the potential worse: " << Potential << " vs. " << OldPotential << "!" << endl;1334 //*out << Verbose(3) << "Setting " << *Runner << "'s source to " << *DistanceIterators[Runner->nr]->second << "." << endl;1335 // Undo for Runner (note, we haven't moved the iteration yet, we may use this)1336 PermutationMap[Runner->nr] = DistanceIterators[Runner->nr]->second;1337 // Undo for Walker1338 DistanceIterators[Walker->nr] = Strider; // take next farther distance target1339 //*out << Verbose(3) << "Setting " << *Walker << "'s source to " << *DistanceIterators[Walker->nr]->second << "." << endl;1340 PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second;1341 } else {1342 DistanceIterators[Runner->nr] = Rider; // if successful also move the pointer in the iterator list1343 *out << Verbose(3) << "Found a better permutation, new potential is " << Potential << " vs." << OldPotential << "." << endl;1344 OldPotential = Potential;1345 }1346 if (Potential > constants[2]) {1347 cerr << "ERROR: The two-step permutation procedure did not maintain injectivity!" << endl;1348 exit(255);1349 }1350 //*out << endl;1351 } else {1352 cerr << "ERROR: " << *Runner << " was not the owner of " << *Sprinter << "!" << endl;1353 exit(255);1354 }1355 } else {1356 PermutationMap[Walker->nr] = DistanceIterators[Walker->nr]->second; // new target has no source!1357 }1358 StepList[Walker->nr]++; // take next farther distance target1359 }1360 } while (Walker->next != end);1361 } while ((OlderPotential - OldPotential) > 1e-3);1362 *out << Verbose(1) << "done." << endl;1363 1364 1365 /// free memory and return with evaluated potential1366 for (int i=AtomCount; i--;)1367 DistanceList[i]->clear();1368 Free((void **)&DistanceList, "molecule::MinimiseConstrainedPotential: **DistanceList");1369 Free((void **)&DistanceIterators, "molecule::MinimiseConstrainedPotential: *DistanceIterators");1370 return ConstrainedPotential(out, PermutationMap, startstep, endstep, constants, IsAngstroem);1371 };1372 1373 /** Evaluates the (distance-related part) of the constrained potential for the constrained forces.1374 * \param *out output stream for debugging1375 * \param startstep current MD step giving initial position between which and \a endstep we perform the constrained MD (as further steps are always concatenated)1376 * \param endstep step giving final position in constrained MD1377 * \param **PermutationMap mapping between the atom label of the initial and the final configuration1378 * \param *Force ForceMatrix containing force vectors from the external energy functional minimisation.1379 * \todo the constant for the constrained potential distance part is hard-coded independently of the hard-coded value in MinimiseConstrainedPotential()1380 */1381 void molecule::EvaluateConstrainedForces(ofstream *out, int startstep, int endstep, atom **PermutationMap, ForceMatrix *Force)1382 {1383 double constant = 10.;1384 atom *Walker = NULL, *Sprinter = NULL;1385 1386 /// evaluate forces (only the distance to target dependent part) with the final PermutationMap1387 *out << Verbose(1) << "Calculating forces and adding onto ForceMatrix ... " << endl;1388 Walker = start;1389 while (Walker->next != NULL) {1390 Walker = Walker->next;1391 Sprinter = PermutationMap[Walker->nr];1392 // set forces1393 for (int i=NDIM;i++;)1394 Force->Matrix[0][Walker->nr][5+i] += 2.*constant*sqrt(Trajectories[Walker].R.at(startstep).Distance(&Trajectories[Sprinter].R.at(endstep)));1395 }1396 *out << Verbose(1) << "done." << endl;1397 };1398 1399 /** Performs a linear interpolation between two desired atomic configurations with a given number of steps.1400 * Note, step number is config::MaxOuterStep1401 * \param *out output stream for debugging1402 * \param startstep stating initial configuration in molecule::Trajectories1403 * \param endstep stating final configuration in molecule::Trajectories1404 * \param &config configuration structure1405 * \return true - success in writing step files, false - error writing files or only one step in molecule::Trajectories1406 */1407 bool molecule::LinearInterpolationBetweenConfiguration(ofstream *out, int startstep, int endstep, const char *prefix, config &configuration)1408 {1409 bool status = true;1410 int MaxSteps = configuration.MaxOuterStep;1411 MoleculeListClass *MoleculePerStep = new MoleculeListClass(MaxSteps+1, AtomCount);1412 // Get the Permutation Map by MinimiseConstrainedPotential1413 atom **PermutationMap = NULL;1414 atom *Walker = NULL, *Sprinter = NULL;1415 MinimiseConstrainedPotential(out, PermutationMap, startstep, endstep, configuration.GetIsAngstroem());1416 1417 // check whether we have sufficient space in Trajectories for each atom1418 Walker = start;1419 while (Walker->next != end) {1420 Walker = Walker->next;1421 if (Trajectories[Walker].R.size() <= (unsigned int)(MaxSteps)) {1422 //cout << "Increasing size for trajectory array of " << keyword << " to " << (MaxSteps+1) << "." << endl;1423 Trajectories[Walker].R.resize(MaxSteps+1);1424 Trajectories[Walker].U.resize(MaxSteps+1);1425 Trajectories[Walker].F.resize(MaxSteps+1);1426 }1427 }1428 // push endstep to last one1429 Walker = start;1430 while (Walker->next != end) { // remove the endstep (is now the very last one)1431 Walker = Walker->next;1432 for (int n=NDIM;n--;) {1433 Trajectories[Walker].R.at(MaxSteps).x[n] = Trajectories[Walker].R.at(endstep).x[n];1434 Trajectories[Walker].U.at(MaxSteps).x[n] = Trajectories[Walker].U.at(endstep).x[n];1435 Trajectories[Walker].F.at(MaxSteps).x[n] = Trajectories[Walker].F.at(endstep).x[n];1436 }1437 }1438 endstep = MaxSteps;1439 1440 // go through all steps and add the molecular configuration to the list and to the Trajectories of \a this molecule1441 *out << Verbose(1) << "Filling intermediate " << MaxSteps << " steps with MDSteps of " << MDSteps << "." << endl;1442 for (int step = 0; step <= MaxSteps; step++) {1443 MoleculePerStep->ListOfMolecules[step] = new molecule(elemente);1444 Walker = start;1445 while (Walker->next != end) {1446 Walker = Walker->next;1447 // add to molecule list1448 Sprinter = MoleculePerStep->ListOfMolecules[step]->AddCopyAtom(Walker);1449 for (int n=NDIM;n--;) {1450 Sprinter->x.x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);1451 // add to Trajectories1452 //*out << Verbose(3) << step << ">=" << MDSteps-1 << endl;1453 if (step < MaxSteps) {1454 Trajectories[Walker].R.at(step).x[n] = Trajectories[Walker].R.at(startstep).x[n] + (Trajectories[PermutationMap[Walker->nr]].R.at(endstep).x[n] - Trajectories[Walker].R.at(startstep).x[n])*((double)step/(double)MaxSteps);1455 Trajectories[Walker].U.at(step).x[n] = 0.;1456 Trajectories[Walker].F.at(step).x[n] = 0.;1457 }1458 }1459 }1460 }1461 MDSteps = MaxSteps+1; // otherwise new Trajectories' points aren't stored on save&exit1462 1463 // store the list to single step files1464 int *SortIndex = (int *) Malloc(AtomCount*sizeof(int), "molecule::LinearInterpolationBetweenConfiguration: *SortIndex");1465 for (int i=AtomCount; i--; )1466 SortIndex[i] = i;1467 status = MoleculePerStep->OutputConfigForListOfFragments(out, "ConstrainedStep", &configuration, SortIndex, false, false);1468 1469 // free and return1470 Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap");1471 delete(MoleculePerStep);1472 return status;1473 };1474 1475 1011 /** Parses nuclear forces from file and performs Verlet integration. 1476 1012 * Note that we assume the parsed forces to be in atomic units (hence, if coordinates are in angstroem, we 1477 1013 * have to transform them). 1478 1014 * This adds a new MD step to the config file. 1479 * \param *out output stream for debugging1480 1015 * \param *file filename 1481 1016 * \param delta_t time step width in atomic units 1482 1017 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false) 1483 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()1484 1018 * \return true - file found and parsed, false - file not found or imparsable 1485 * \todo This is not yet checked if it is correctly working with DoConstrained set to true. 1486 */ 1487 bool molecule::VerletForceIntegration(ofstream *out, char *file, double delta_t, bool IsAngstroem, int DoConstrained) 1019 */ 1020 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1488 1021 { 1489 1022 element *runner = elemente->start; … … 1493 1026 string token; 1494 1027 stringstream item; 1495 double a, IonMass , Vector[NDIM], ConstrainedPotentialEnergy;1028 double a, IonMass; 1496 1029 ForceMatrix Force; 1030 Vector tmpvector; 1497 1031 1498 1032 CountElements(); // make sure ElementsInMolecule is up to date 1499 1033 1500 1034 // check file 1501 1035 if (input == NULL) { … … 1512 1046 } 1513 1047 // correct Forces 1514 for(int d=0;d<NDIM;d++) 1515 Vector[d] = 0.; 1516 for(int i=0;i<AtomCount;i++) 1517 for(int d=0;d<NDIM;d++) { 1518 Vector[d] += Force.Matrix[0][i][d+5]; 1519 } 1520 for(int i=0;i<AtomCount;i++) 1521 for(int d=0;d<NDIM;d++) { 1522 Force.Matrix[0][i][d+5] -= Vector[d]/(double)AtomCount; 1523 } 1524 // solve a constrained potential if we are meant to 1525 if (DoConstrained) { 1526 // calculate forces and potential 1527 atom **PermutationMap = NULL; 1528 ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap, DoConstrained, 0, IsAngstroem); 1529 EvaluateConstrainedForces(out, DoConstrained, 0, PermutationMap, &Force); 1530 Free((void **)&PermutationMap, "molecule::MinimiseConstrainedPotential: *PermutationMap"); 1531 } 1532 1048 // for(int d=0;d<NDIM;d++) 1049 // tmpvector.x[d] = 0.; 1050 // for(int i=0;i<AtomCount;i++) 1051 // for(int d=0;d<NDIM;d++) { 1052 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1053 // } 1054 // for(int i=0;i<AtomCount;i++) 1055 // for(int d=0;d<NDIM;d++) { 1056 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1057 // } 1533 1058 // and perform Verlet integration for each atom with position, velocity and force vector 1534 1059 runner = elemente->start; … … 1545 1070 // check size of vectors 1546 1071 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1547 // out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;1072 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1548 1073 Trajectories[walker].R.resize(MDSteps+10); 1549 1074 Trajectories[walker].U.resize(MDSteps+10); 1550 1075 Trajectories[walker].F.resize(MDSteps+10); 1551 1076 } 1552 1553 // Update R (and F) 1077 // 1. calculate x(t+\delta t) 1554 1078 for (int d=0; d<NDIM; d++) { 1555 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5] *(IsAngstroem ? AtomicLengthToAngstroem : 1.);1079 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1556 1080 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1557 1081 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1558 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*a*(Trajectories[walker].F.at(MDSteps).x[d]); // F = m * a and s = 0.5 * F/m * t^2 = F * a * t1082 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass; // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1559 1083 } 1560 // Update U1084 // 2. Calculate v(t+\delta t) 1561 1085 for (int d=0; d<NDIM; d++) { 1562 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1563 Trajectories[walker].U.at(MDSteps).x[d] += a * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]);1086 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 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; 1564 1088 } 1565 // out << "Integrated position&velocity of step " << (MDSteps) << ": (";1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1566 1090 // for (int d=0;d<NDIM;d++) 1567 // out << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step1568 // out << ")\t(";1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1092 // cout << ")\t("; 1569 1093 // for (int d=0;d<NDIM;d++) 1570 1094 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1571 // out << ")" << endl;1095 // cout << ")" << endl; 1572 1096 // next atom 1573 1097 AtomNo++; … … 1578 1102 } 1579 1103 // // correct velocities (rather momenta) so that center of mass remains motionless 1580 // for(int d=0;d<NDIM;d++) 1581 // Vector[d] = 0.; 1104 // tmpvector.zero() 1582 1105 // IonMass = 0.; 1583 1106 // walker = start; … … 1586 1109 // IonMass += walker->type->mass; // sum up total mass 1587 1110 // for(int d=0;d<NDIM;d++) { 1588 // Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;1111 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1589 1112 // } 1590 1113 // } … … 1593 1116 // walker = walker->next; 1594 1117 // for(int d=0;d<NDIM;d++) { 1595 // Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d]*walker->type->mass/IonMass;1118 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1596 1119 // } 1597 1120 // } 1598 1121 MDSteps++; 1599 1122 1600 1123 1601 1124 // exit 1602 1125 return true; 1603 1126 }; 1604 1127 1605 /** 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. 1606 1129 * \param n[] alignment vector. 1607 1130 */ … … 1622 1145 ptr = ptr->next; 1623 1146 tmp = ptr->x.x[0]; 1624 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]; 1625 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1626 1149 for (int j=0;j<MDSteps;j++) { 1627 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1628 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]; 1629 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1630 1153 } 1631 } 1154 } 1632 1155 // rotate n vector 1633 1156 tmp = n->x[0]; … … 1637 1160 n->Output((ofstream *)&cout); 1638 1161 cout << endl; 1639 1162 1640 1163 // rotate on z-y plane 1641 1164 ptr = start; … … 1645 1168 ptr = ptr->next; 1646 1169 tmp = ptr->x.x[1]; 1647 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]; 1648 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1649 1172 for (int j=0;j<MDSteps;j++) { 1650 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1651 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]; 1652 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1653 1176 } 1654 } 1177 } 1655 1178 // rotate n vector (for consistency check) 1656 1179 tmp = n->x[1]; 1657 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1658 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1659 1182 1660 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1661 1184 n->Output((ofstream *)&cout); … … 1668 1191 * \return true - succeeded, false - atom not found in list 1669 1192 */ 1670 bool molecule::RemoveAtom(atom *pointer) 1671 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1672 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1673 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1674 1197 else 1675 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; 1676 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1677 1200 ElementCount--; … … 1683 1206 * \return true - succeeded, false - atom not found in list 1684 1207 */ 1685 bool molecule::CleanupMolecule() 1686 { 1687 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1688 1211 }; 1689 1212 … … 1699 1222 } else { 1700 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1701 return NULL; 1224 return NULL; 1702 1225 } 1703 1226 }; … … 1748 1271 struct lsq_params *par = (struct lsq_params *)params; 1749 1272 atom *ptr = par->mol->start; 1750 1273 1751 1274 // initialize vectors 1752 1275 a.x[0] = gsl_vector_get(x,0); … … 1778 1301 { 1779 1302 int np = 6; 1780 1303 1781 1304 const gsl_multimin_fminimizer_type *T = 1782 1305 gsl_multimin_fminimizer_nmsimplex; … … 1784 1307 gsl_vector *ss; 1785 1308 gsl_multimin_function minex_func; 1786 1309 1787 1310 size_t iter = 0, i; 1788 1311 int status; 1789 1312 double size; 1790 1313 1791 1314 /* Initial vertex size vector */ 1792 1315 ss = gsl_vector_alloc (np); 1793 1316 1794 1317 /* Set all step sizes to 1 */ 1795 1318 gsl_vector_set_all (ss, 1.0); 1796 1319 1797 1320 /* Starting point */ 1798 1321 par->x = gsl_vector_alloc (np); 1799 1322 par->mol = this; 1800 1323 1801 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1802 1325 gsl_vector_set (par->x, 1, 0.0); … … 1805 1328 gsl_vector_set (par->x, 4, 0.0); 1806 1329 gsl_vector_set (par->x, 5, 1.0); 1807 1330 1808 1331 /* Initialize method and iterate */ 1809 1332 minex_func.f = &LeastSquareDistance; 1810 1333 minex_func.n = np; 1811 1334 minex_func.params = (void *)par; 1812 1335 1813 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1814 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1815 1338 1816 1339 do 1817 1340 { 1818 1341 iter++; 1819 1342 status = gsl_multimin_fminimizer_iterate(s); 1820 1343 1821 1344 if (status) 1822 1345 break; 1823 1346 1824 1347 size = gsl_multimin_fminimizer_size (s); 1825 1348 status = gsl_multimin_test_size (size, 1e-2); 1826 1349 1827 1350 if (status == GSL_SUCCESS) 1828 1351 { 1829 1352 printf ("converged to minimum at\n"); 1830 1353 } 1831 1354 1832 1355 printf ("%5d ", (int)iter); 1833 1356 for (i = 0; i < (size_t)np; i++) … … 1838 1361 } 1839 1362 while (status == GSL_CONTINUE && iter < 100); 1840 1363 1841 1364 for (i=0;i<(size_t)np;i++) 1842 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 1855 1378 int ElementNo, AtomNo; 1856 1379 CountElements(); 1857 1380 1858 1381 if (out == NULL) { 1859 1382 return false; … … 1890 1413 int ElementNo, AtomNo; 1891 1414 CountElements(); 1892 1415 1893 1416 if (out == NULL) { 1894 1417 return false; … … 1937 1460 atom *Walker = start; 1938 1461 while (Walker->next != end) { 1939 Walker = Walker->next; 1462 Walker = Walker->next; 1940 1463 #ifdef ADDHYDROGEN 1941 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 1968 1491 int No = 0; 1969 1492 time_t now; 1970 1493 1971 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1972 1495 walker = start; … … 1995 1518 { 1996 1519 atom *walker = NULL; 1997 int No = 0;1520 int AtomNo = 0, ElementNo; 1998 1521 time_t now; 1999 1522 element *runner = NULL; 1523 2000 1524 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2001 1525 walker = start; 2002 1526 while (walker->next != end) { // go through every atom and count 2003 1527 walker = walker->next; 2004 No++;1528 AtomNo++; 2005 1529 } 2006 1530 if (out != NULL) { 2007 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 2008 walker = start; 2009 while (walker->next != end) { // go through every atom of this element 2010 walker = walker->next; 2011 walker->OutputXYZLine(out); 1531 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1532 ElementNo = 0; 1533 runner = elemente->start; 1534 while (runner->next != elemente->end) { // go through every element 1535 runner = runner->next; 1536 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1537 ElementNo++; 1538 walker = start; 1539 while (walker->next != end) { // go through every atom of this element 1540 walker = walker->next; 1541 if (walker->type == runner) { // if this atom fits to element 1542 walker->OutputXYZLine(out); 1543 } 1544 } 1545 } 2012 1546 } 2013 1547 return true; … … 2040 1574 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 2041 1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 2042 NoNonHydrogen++; 1576 NoNonHydrogen++; 2043 1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 2044 1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 2048 1582 } 2049 1583 } else 2050 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2051 1585 } 2052 1586 }; … … 2060 1594 ElementsInMolecule[i] = 0; 2061 1595 ElementCount = 0; 2062 1596 2063 1597 atom *walker = start; 2064 1598 while (walker->next != end) { … … 2096 1630 Binder = Binder->next; 2097 1631 if (Binder->Cyclic) 2098 No++; 1632 No++; 2099 1633 } 2100 1634 delete(BackEdgeStack); … … 2154 1688 2155 1689 /** Creates an adjacency list of the molecule. 1690 * We obtain an outside file with the indices of atoms which are bondmembers. 1691 */ 1692 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input) 1693 { 1694 1695 // 1 We will parse bonds out of the dbond file created by tremolo. 1696 int atom1, atom2, temp; 1697 atom *Walker, *OtherWalker; 1698 1699 if (!input) 1700 { 1701 cout << Verbose(1) << "Opening silica failed \n"; 1702 }; 1703 1704 *input >> ws >> atom1; 1705 *input >> ws >> atom2; 1706 cout << Verbose(1) << "Scanning file\n"; 1707 while (!input->eof()) // Check whether we read everything already 1708 { 1709 *input >> ws >> atom1; 1710 *input >> ws >> atom2; 1711 if(atom2<atom1) //Sort indices of atoms in order 1712 { 1713 temp=atom1; 1714 atom1=atom2; 1715 atom2=temp; 1716 }; 1717 1718 Walker=start; 1719 while(Walker-> nr != atom1) // Find atom corresponding to first index 1720 { 1721 Walker = Walker->next; 1722 }; 1723 OtherWalker = Walker->next; 1724 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1725 { 1726 OtherWalker= OtherWalker->next; 1727 }; 1728 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1729 1730 } 1731 1732 CreateListOfBondsPerAtom(out); 1733 1734 }; 1735 1736 1737 /** Creates an adjacency list of the molecule. 2156 1738 * Generally, we use the CSD approach to bond recognition, that is the the distance 2157 1739 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 2158 * a threshold t = 0.4 Angstroem. 1740 * a threshold t = 0.4 Angstroem. 2159 1741 * To make it O(N log N) the function uses the linked-cell technique as follows: 2160 1742 * The procedure is step-wise: … … 2173 1755 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 2174 1756 { 1757 2175 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 2176 1759 int No, NoBonds, CandidateBondNo; … … 2181 1764 Vector x; 2182 1765 int FalseBondDegree = 0; 2183 1766 2184 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 2185 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 2188 1771 cleanup(first,last); 2189 1772 } 2190 1773 2191 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 2192 1775 CountAtoms(out); … … 2207 1790 for (int i=NumberCells;i--;) 2208 1791 CellList[i] = NULL; 2209 1792 2210 1793 // 2b. put all atoms into its corresponding list 2211 1794 Walker = start; … … 2228 1811 if (CellList[index] == NULL) // allocate molecule if not done 2229 1812 CellList[index] = new molecule(elemente); 2230 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 2231 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1813 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1814 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 2232 1815 } 2233 1816 //for (int i=0;i<NumberCells;i++) 2234 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 2235 1818 1819 2236 1820 // 3a. go through every cell 2237 1821 for (N[0]=divisor[0];N[0]--;) … … 2246 1830 Walker = Walker->next; 2247 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 2248 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1832 // 3c. check for possible bond between each atom in this and every one in the 27 cells 2249 1833 for (n[0]=-1;n[0]<=1;n[0]++) 2250 1834 for (n[1]=-1;n[1]<=1;n[1]++) … … 2278 1862 } 2279 1863 } 1864 1865 1866 2280 1867 // 4. free the cell again 2281 1868 for (int i=NumberCells;i--;) … … 2284 1871 } 2285 1872 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 2286 1873 2287 1874 // create the adjacency list per atom 2288 1875 CreateListOfBondsPerAtom(out); 2289 1876 2290 1877 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 2291 1878 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 2336 1923 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 2337 1924 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 2338 1925 2339 1926 // output bonds for debugging (if bond chain list was correctly installed) 2340 1927 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 2346 1933 *out << endl; 2347 1934 } else 2348 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1935 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2349 1936 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2350 1937 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2351 }; 1938 1939 }; 1940 1941 2352 1942 2353 1943 /** Performs a Depth-First search on this molecule. … … 2370 1960 bond *Binder = NULL; 2371 1961 bool BackStepping = false; 2372 1962 2373 1963 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2374 1964 2375 1965 ResetAllBondsToUnused(); 2376 1966 ResetAllAtomNumbers(); … … 2385 1975 LeafWalker->Leaf = new molecule(elemente); 2386 1976 LeafWalker->Leaf->AddCopyAtom(Root); 2387 1977 2388 1978 OldGraphNr = CurrentGraphNr; 2389 1979 Walker = Root; … … 2396 1986 AtomStack->Push(Walker); 2397 1987 CurrentGraphNr++; 2398 } 1988 } 2399 1989 do { // (3) if Walker has no unused egdes, go to (5) 2400 1990 BackStepping = false; // reset backstepping flag for (8) … … 2430 2020 Binder = NULL; 2431 2021 } while (1); // (2) 2432 2022 2433 2023 // 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! 2434 2024 if ((Walker == Root) && (Binder == NULL)) 2435 2025 break; 2436 2437 // (5) if Ancestor of Walker is ... 2026 2027 // (5) if Ancestor of Walker is ... 2438 2028 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2439 2029 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2478 2068 } while (OtherAtom != Walker); 2479 2069 ComponentNumber++; 2480 2070 2481 2071 // (11) Root is separation vertex, set Walker to Root and go to (4) 2482 2072 Walker = Root; … … 2491 2081 2492 2082 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2493 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2083 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2494 2084 LeafWalker->Leaf->Output(out); 2495 2085 *out << endl; … … 2499 2089 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2500 2090 if (Root->GraphNr != -1) // if already discovered, step on 2501 Root = Root->next; 2091 Root = Root->next; 2502 2092 } 2503 2093 } … … 2521 2111 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2522 2112 } 2523 2113 2524 2114 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2525 2115 Binder = first; … … 2532 2122 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2533 2123 OutputComponentNumber(out, Binder->rightatom); 2534 *out << ">." << endl; 2124 *out << ">." << endl; 2535 2125 if (Binder->Cyclic) // cyclic ?? 2536 2126 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2547 2137 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2548 2138 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2549 * as cyclic and print out the cycles. 2139 * as cyclic and print out the cycles. 2550 2140 * \param *out output stream for debugging 2551 2141 * \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! … … 2558 2148 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2559 2149 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2560 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2150 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2561 2151 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2562 2152 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2570 2160 ColorList[i] = white; 2571 2161 } 2572 2162 2573 2163 *out << Verbose(1) << "Back edge list - "; 2574 2164 BackEdgeStack->Output(out); 2575 2165 2576 2166 *out << Verbose(1) << "Analysing cycles ... " << endl; 2577 2167 NumCycles = 0; … … 2579 2169 BackEdge = BackEdgeStack->PopFirst(); 2580 2170 // this is the target 2581 Root = BackEdge->leftatom; 2171 Root = BackEdge->leftatom; 2582 2172 // this is the source point 2583 Walker = BackEdge->rightatom; 2173 Walker = BackEdge->rightatom; 2584 2174 ShortestPathList[Walker->nr] = 0; 2585 2175 BFSStack->ClearStack(); // start with empty BFS stack … … 2595 2185 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2596 2186 OtherAtom = Binder->GetOtherAtom(Walker); 2597 #ifdef ADDHYDROGEN 2187 #ifdef ADDHYDROGEN 2598 2188 if (OtherAtom->type->Z != 1) { 2599 2189 #endif … … 2604 2194 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2605 2195 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2606 *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; 2196 *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; 2607 2197 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2608 2198 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2614 2204 if (OtherAtom == Root) 2615 2205 break; 2616 #ifdef ADDHYDROGEN 2206 #ifdef ADDHYDROGEN 2617 2207 } else { 2618 2208 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2652 2242 } 2653 2243 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2654 2244 2655 2245 if (OtherAtom == Root) { 2656 2246 // now climb back the predecessor list and thus find the cycle members … … 2680 2270 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2681 2271 } 2682 2272 2683 2273 // now clean the lists 2684 2274 while (!TouchedStack->IsEmpty()){ … … 2690 2280 } 2691 2281 if (MinRingSize != -1) { 2692 // go over all atoms 2282 // go over all atoms 2693 2283 Root = start; 2694 2284 while(Root->next != end) { 2695 2285 Root = Root->next; 2696 2286 2697 2287 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2698 2288 Walker = Root; … … 2731 2321 } 2732 2322 ColorList[Walker->nr] = black; 2733 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2323 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2734 2324 } 2735 2325 2736 2326 // now clean the lists 2737 2327 while (!TouchedStack->IsEmpty()){ … … 2782 2372 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2783 2373 { 2784 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2374 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2785 2375 *out << vertex->ComponentNr[i] << " "; 2786 2376 }; … … 2860 2450 { 2861 2451 int c = 0; 2862 int FragmentCount; 2452 int FragmentCount; 2863 2453 // get maximum bond degree 2864 2454 atom *Walker = start; … … 2870 2460 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2871 2461 return FragmentCount; 2872 }; 2462 }; 2873 2463 2874 2464 /** Scans a single line for number and puts them into \a KeySet. 2875 2465 * \param *out output stream for debugging 2876 2466 * \param *buffer buffer to scan 2877 * \param &CurrentSet filled KeySet on return 2467 * \param &CurrentSet filled KeySet on return 2878 2468 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 2879 2469 */ … … 2883 2473 int AtomNr; 2884 2474 int status = 0; 2885 2475 2886 2476 line.str(buffer); 2887 2477 while (!line.eof()) { … … 2919 2509 double TEFactor; 2920 2510 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2921 2511 2922 2512 if (FragmentList == NULL) { // check list pointer 2923 2513 FragmentList = new Graph; 2924 2514 } 2925 2515 2926 2516 // 1st pass: open file and read 2927 2517 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 2952 2542 status = false; 2953 2543 } 2954 2544 2955 2545 // 2nd pass: open TEFactors file and read 2956 2546 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 2964 2554 InputFile >> TEFactor; 2965 2555 (*runner).second.second = TEFactor; 2966 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2556 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2967 2557 } else { 2968 2558 status = false; … … 3005 2595 if(output != NULL) { 3006 2596 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 3007 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2597 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3008 2598 if (sprinter != (*runner).first.begin()) 3009 2599 output << "\t"; … … 3071 2661 status = false; 3072 2662 } 3073 2663 3074 2664 return status; 3075 2665 }; … … 3080 2670 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 3081 2671 * \return true - structure is equal, false - not equivalence 3082 */ 2672 */ 3083 2673 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 3084 2674 { … … 3087 2677 bool status = true; 3088 2678 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3089 2679 3090 2680 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 3091 2681 File.open(filename.str().c_str(), ios::out); … … 3146 2736 *out << endl; 3147 2737 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3148 2738 3149 2739 return status; 3150 2740 }; … … 3168 2758 for(int i=AtomCount;i--;) 3169 2759 AtomMask[i] = false; 3170 2760 3171 2761 if (Order < 0) { // adaptive increase of BondOrder per site 3172 2762 if (AtomMask[AtomCount] == true) // break after one step … … 3208 2798 line >> ws >> Value; // skip time entry 3209 2799 line >> ws >> Value; 3210 No -= 1; // indices start at 1 in file, not 0 2800 No -= 1; // indices start at 1 in file, not 0 3211 2801 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 3212 2802 … … 3217 2807 // 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 3218 2808 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 3219 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2809 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3220 2810 if (!InsertedElement.second) { // this root is already present 3221 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 3222 //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) 2811 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2812 //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) 3223 2813 { // if value is smaller, update value and order 3224 2814 (*PresentItem).second.first = fabs(Value); … … 3258 2848 Walker = FindAtom(No); 3259 2849 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 3260 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2850 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 3261 2851 AtomMask[No] = true; 3262 2852 status = true; 3263 2853 //} else 3264 //*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; 2854 //*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; 3265 2855 } 3266 2856 // close and done … … 3296 2886 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 3297 2887 status = true; 3298 2888 3299 2889 if (!status) { 3300 2890 if (Order == 0) … … 3304 2894 } 3305 2895 } 3306 2896 3307 2897 // print atom mask for debugging 3308 2898 *out << " "; … … 3313 2903 *out << (AtomMask[i] ? "t" : "f"); 3314 2904 *out << endl; 3315 2905 3316 2906 return status; 3317 2907 }; … … 3327 2917 int AtomNo = 0; 3328 2918 atom *Walker = NULL; 3329 2919 3330 2920 if (SortIndex != NULL) { 3331 2921 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 3385 2975 atom **ListOfAtoms = NULL; 3386 2976 atom ***ListOfLocalAtoms = NULL; 3387 bool *AtomMask = NULL; 3388 2977 bool *AtomMask = NULL; 2978 3389 2979 *out << endl; 3390 2980 #ifdef ADDHYDROGEN … … 3395 2985 3396 2986 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3397 2987 3398 2988 // ===== 1. Check whether bond structure is same as stored in files ==== 3399 2989 3400 2990 // fill the adjacency list 3401 2991 CreateListOfBondsPerAtom(out); … … 3403 2993 // create lookup table for Atom::nr 3404 2994 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3405 2995 3406 2996 // === compare it with adjacency file === 3407 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2997 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3408 2998 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3409 2999 … … 3419 3009 while (MolecularWalker->next != NULL) { 3420 3010 MolecularWalker = MolecularWalker->next; 3421 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3422 3011 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3423 3012 // // check the list of local atoms for debugging … … 3428 3017 // else 3429 3018 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3019 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3430 3020 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3021 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3431 3022 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3023 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3432 3024 delete(LocalBackEdgeStack); 3433 3025 } 3434 3026 3435 3027 // ===== 3. if structure still valid, parse key set file and others ===== 3436 3028 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 3438 3030 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3439 3031 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3440 3441 // =================================== Begin of FRAGMENTATION =============================== 3442 // ===== 6a. assign each keyset to its respective subgraph ===== 3032 3033 // =================================== Begin of FRAGMENTATION =============================== 3034 // ===== 6a. assign each keyset to its respective subgraph ===== 3443 3035 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3444 3036 … … 3451 3043 FragmentationToDo = FragmentationToDo || CheckOrder; 3452 3044 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3453 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3045 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3454 3046 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3455 3047 … … 3460 3052 MolecularWalker = MolecularWalker->next; 3461 3053 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3462 // output ListOfBondsPerAtom for debugging 3463 MolecularWalker->Leaf->OutputListOfBonds(out); 3054 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3464 3055 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3465 3466 3056 // call BOSSANOVA method 3467 3057 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; … … 3477 3067 delete(ParsedFragmentList); 3478 3068 delete[](MinimumRingSize); 3479 3069 3480 3070 3481 3071 // ==================================== End of FRAGMENTATION ============================================ … … 3483 3073 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3484 3074 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3485 3075 3486 3076 // free subgraph memory again 3487 3077 FragmentCounter = 0; … … 3508 3098 } 3509 3099 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3510 3100 3511 3101 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3512 3102 if (BondFragments->NumberOfMolecules != 0) { 3513 3103 // create the SortIndex from BFS labels to order in the config file 3514 3104 CreateMappingLabelsToConfigSequence(out, SortIndex); 3515 3105 3516 3106 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3517 if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true))3107 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3518 3108 *out << Verbose(1) << "All configs written." << endl; 3519 3109 else 3520 3110 *out << Verbose(1) << "Some config writing failed." << endl; 3521 3111 3522 3112 // store force index reference file 3523 3113 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3524 3525 // store keysets file 3114 3115 // store keysets file 3526 3116 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3527 3528 // store Adjacency file 3117 3118 // store Adjacency file 3529 3119 StoreAdjacencyToFile(out, configuration->configpath); 3530 3120 3531 3121 // store Hydrogen saturation correction file 3532 3122 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3533 3123 3534 3124 // store adaptive orders into file 3535 3125 StoreOrderAtSiteFile(out, configuration->configpath); 3536 3126 3537 3127 // restore orbital and Stop values 3538 3128 CalculateOrbitals(*configuration); 3539 3129 3540 3130 // free memory for bond part 3541 3131 *out << Verbose(1) << "Freeing bond memory" << endl; 3542 3132 delete(FragmentList); // remove bond molecule from memory 3543 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3133 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3544 3134 } else 3545 3135 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3546 //} else 3136 //} else 3547 3137 // *out << Verbose(1) << "No fragments to store." << endl; 3548 3138 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3570 3160 atom *Walker = NULL, *OtherAtom = NULL; 3571 3161 ReferenceStack->Push(Binder); 3572 3162 3573 3163 do { // go through all bonds and push local ones 3574 3164 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3575 if (Walker == NULL) // if this Walker exists in the subgraph ...3576 continue;3577 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds3578 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3579 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3580 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3581 break;3582 }3583 }3165 if (Walker != NULL) // if this Walker exists in the subgraph ... 3166 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3167 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3168 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3169 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3170 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3171 break; 3172 } 3173 } 3584 3174 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3175 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3585 3176 ReferenceStack->Push(Binder); 3586 3177 } while (FirstBond != Binder); 3587 3178 3588 3179 return status; 3589 3180 }; … … 3661 3252 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3662 3253 Walker->MaxOrder = MaxArray[Walker->nr]; 3663 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3254 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3664 3255 } 3665 3256 file.close(); … … 3672 3263 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3673 3264 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3674 3265 3675 3266 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3676 3267 return status; … … 3730 3321 Walker = start; 3731 3322 while (Walker->next != end) { 3732 Walker = Walker->next; 3323 Walker = Walker->next; 3733 3324 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3734 3325 TotalDegree = 0; … … 3738 3329 } 3739 3330 *out << " -- TotalDegree: " << TotalDegree << endl; 3740 } 3331 } 3741 3332 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3742 3333 }; … … 3744 3335 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3745 3336 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3746 * white and putting into queue. 3337 * white and putting into queue. 3747 3338 * \param *out output stream for debugging 3748 3339 * \param *Mol Molecule class to add atoms to … … 3753 3344 * \param BondOrder maximum distance for vertices to add 3754 3345 * \param IsAngstroem lengths are in angstroem or bohrradii 3755 */ 3346 */ 3756 3347 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3757 3348 { … … 3779 3370 } 3780 3371 ShortestPathList[Root->nr] = 0; 3781 3372 3782 3373 // and go on ... Queue always contains all lightgray vertices 3783 3374 while (!AtomStack->IsEmpty()) { … … 3787 3378 // followed by n+1 till top of stack. 3788 3379 Walker = AtomStack->PopFirst(); // pop oldest added 3789 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3380 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3790 3381 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3791 3382 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3794 3385 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3795 3386 if (ColorList[OtherAtom->nr] == white) { 3796 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) 3387 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) 3797 3388 ColorList[OtherAtom->nr] = lightgray; 3798 3389 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3799 3390 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3800 *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; 3391 *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; 3801 3392 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3802 3393 *out << Verbose(3); … … 3836 3427 } else { 3837 3428 #ifdef ADDHYDROGEN 3838 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 3429 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3430 exit(1); 3839 3431 #endif 3840 3432 } … … 3845 3437 // This has to be a cyclic bond, check whether it's present ... 3846 3438 if (AddedBondList[Binder->nr] == NULL) { 3847 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3439 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3848 3440 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3849 3441 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3851 3443 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3852 3444 #ifdef ADDHYDROGEN 3853 Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem); 3445 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3446 exit(1); 3854 3447 #endif 3855 3448 } … … 3859 3452 } 3860 3453 ColorList[Walker->nr] = black; 3861 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3454 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3862 3455 } 3863 3456 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 3883 3476 3884 3477 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3885 3478 3886 3479 // reset parent list 3887 3480 *out << Verbose(3) << "Resetting ParentList." << endl; 3888 3481 for (int i=Father->AtomCount;i--;) 3889 3482 ParentList[i] = NULL; 3890 3483 3891 3484 // fill parent list with sons 3892 3485 *out << Verbose(3) << "Filling Parent List." << endl; … … 3929 3522 * \param *&Leaf KeySet to look through 3930 3523 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 3931 * \param index of the atom suggested for removal 3524 * \param index of the atom suggested for removal 3932 3525 */ 3933 3526 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 3935 3528 atom *Runner = NULL; 3936 3529 int SP, Removal; 3937 3530 3938 3531 *out << Verbose(2) << "Looking for removal candidate." << endl; 3939 3532 SP = -1; //0; // not -1, so that Root is never removed … … 3953 3546 /** Stores a fragment from \a KeySet into \a molecule. 3954 3547 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 3955 * molecule and adds missing hydrogen where bonds were cut. 3548 * molecule and adds missing hydrogen where bonds were cut. 3956 3549 * \param *out output stream for debugging messages 3957 * \param &Leaflet pointer to KeySet structure 3550 * \param &Leaflet pointer to KeySet structure 3958 3551 * \param IsAngstroem whether we have Ansgtroem or bohrradius 3959 3552 * \return pointer to constructed molecule … … 3966 3559 bool LonelyFlag = false; 3967 3560 int size; 3968 3561 3969 3562 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3970 3563 3971 3564 Leaf->BondDistance = BondDistance; 3972 3565 for(int i=NDIM*2;i--;) 3973 Leaf->cell_size[i] = cell_size[i]; 3566 Leaf->cell_size[i] = cell_size[i]; 3974 3567 3975 3568 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 3984 3577 size++; 3985 3578 } 3986 3579 3987 3580 // create the bonds between all: Make it an induced subgraph and add hydrogen 3988 3581 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 3994 3587 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3995 3588 // create all bonds 3996 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3589 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3997 3590 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3998 3591 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3999 3592 if (SonList[OtherFather->nr] != NULL) { 4000 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3593 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4001 3594 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 4002 3595 // *out << Verbose(3) << "Adding Bond: "; 4003 // *out << 3596 // *out << 4004 3597 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 4005 3598 // *out << "." << endl; 4006 3599 //NumBonds[Runner->nr]++; 4007 } else { 3600 } else { 4008 3601 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 4009 3602 } 4010 3603 LonelyFlag = false; 4011 3604 } else { 4012 // *out << ", who has no son in this fragment molecule." << endl; 3605 // *out << ", who has no son in this fragment molecule." << endl; 4013 3606 #ifdef ADDHYDROGEN 4014 3607 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 4015 Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem); 3608 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3609 exit(1); 4016 3610 #endif 4017 3611 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; … … 4027 3621 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 4028 3622 Runner = Runner->next; 4029 #endif 3623 #endif 4030 3624 } 4031 3625 Leaf->CreateListOfBondsPerAtom(out); … … 4060 3654 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 4061 3655 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! 4062 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3656 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4063 3657 MoleculeListClass *FragmentList = NULL; 4064 3658 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 4110 3704 // clear snake stack 4111 3705 SnakeStack->ClearStack(); 4112 //SnakeStack->TestImplementation(out, start->next); 3706 //SnakeStack->TestImplementation(out, start->next); 4113 3707 4114 3708 ///// INNER LOOP //////////// … … 4131 3725 } 4132 3726 if (ShortestPathList[Walker->nr] == -1) { 4133 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3727 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4134 3728 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 4135 3729 } … … 4169 3763 OtherAtom = Binder->GetOtherAtom(Walker); 4170 3764 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 4171 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3765 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 4172 3766 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 4173 3767 } else { // otherwise check its colour and element 4174 3768 if ( 4175 3769 #ifdef ADDHYDROGEN 4176 (OtherAtom->type->Z != 1) && 3770 (OtherAtom->type->Z != 1) && 4177 3771 #endif 4178 3772 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 4184 3778 //} else { 4185 3779 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 4186 //} 3780 //} 4187 3781 Walker = OtherAtom; 4188 3782 break; 4189 3783 } else { 4190 if (OtherAtom->type->Z == 1) 3784 if (OtherAtom->type->Z == 1) 4191 3785 *out << "Links to a hydrogen atom." << endl; 4192 else 3786 else 4193 3787 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 4194 3788 } … … 4200 3794 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 4201 3795 } 4202 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3796 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4203 3797 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 4204 3798 ColorVertexList[Walker->nr] = black; … … 4207 3801 } 4208 3802 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 4209 *out << Verbose(2) << "Inner Looping is finished." << endl; 3803 *out << Verbose(2) << "Inner Looping is finished." << endl; 4210 3804 4211 3805 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 4223 3817 } 4224 3818 } 4225 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3819 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4226 3820 4227 3821 // copy together 4228 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3822 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4229 3823 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 4230 3824 RunningIndex = 0; … … 4297 3891 4298 3892 NumCombinations = 1 << SetDimension; 4299 3893 4300 3894 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 4301 3895 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 4302 3896 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 4303 3897 4304 3898 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 4305 3899 *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; 4306 3900 4307 // initialised touched list (stores added atoms on this level) 3901 // initialised touched list (stores added atoms on this level) 4308 3902 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 4309 3903 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 4310 3904 TouchedList[TouchedIndex] = -1; 4311 3905 TouchedIndex = 0; 4312 3906 4313 3907 // create every possible combination of the endpieces 4314 3908 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 4318 3912 for (int j=SetDimension;j--;) 4319 3913 bits += (i & (1 << j)) >> j; 4320 3914 4321 3915 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 4322 3916 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 4326 3920 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 4327 3921 if (bit) { // if bit is set, we add this bond partner 4328 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3922 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 4329 3923 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 4330 3924 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 4331 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3925 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4332 3926 if (TestKeySetInsert.second) { 4333 3927 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 4342 3936 } 4343 3937 } 4344 4345 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3938 3939 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 4346 3940 if (SpaceLeft > 0) { 4347 3941 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 4371 3965 } 4372 3966 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 4373 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3967 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4374 3968 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 4375 3969 } … … 4380 3974 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 4381 3975 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4382 *out << (*runner) << " "; 3976 *out << (*runner) << " "; 4383 3977 *out << endl; 4384 3978 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 4388 3982 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 4389 3983 } 4390 3984 4391 3985 // --3-- remove all added items in this level from snake stack 4392 3986 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 4399 3993 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 4400 3994 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4401 *out << (*runner) << " "; 3995 *out << (*runner) << " "; 4402 3996 *out << endl; 4403 3997 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 4406 4000 } 4407 4001 } 4408 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4002 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4409 4003 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 4410 4004 }; … … 4415 4009 * \return true - connected, false - disconnected 4416 4010 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 4417 */ 4011 */ 4418 4012 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 4419 4013 { … … 4421 4015 bool BondStatus = false; 4422 4016 int size; 4423 4017 4424 4018 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 4425 4019 *out << Verbose(2) << "Disconnected atom: "; 4426 4020 4427 4021 // count number of atoms in graph 4428 4022 size = 0; … … 4470 4064 * \param *out output stream for debugging 4471 4065 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 4472 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4066 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4473 4067 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4474 4068 * \return number of inserted fragments 4475 4069 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4476 4070 */ 4477 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4071 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4478 4072 { 4479 4073 int SP, AtomKeyNr; … … 4496 4090 FragmentSearch.BondsPerSPCount[i] = 0; 4497 4091 FragmentSearch.BondsPerSPCount[0] = 1; 4498 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4092 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4499 4093 add(Binder, FragmentSearch.BondsPerSPList[1]); 4500 4094 4501 4095 // do a BFS search to fill the SP lists and label the found vertices 4502 4096 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4503 4097 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4504 4098 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4505 // (EdgeinSPLevel) of this tree ... 4099 // (EdgeinSPLevel) of this tree ... 4506 4100 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4507 4101 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4556 4150 } 4557 4151 } 4558 4152 4559 4153 // outputting all list for debugging 4560 4154 *out << Verbose(0) << "Printing all found lists." << endl; … … 4565 4159 Binder = Binder->next; 4566 4160 *out << Verbose(2) << *Binder << endl; 4567 } 4568 } 4569 4161 } 4162 } 4163 4570 4164 // creating fragments with the found edge sets (may be done in reverse order, faster) 4571 4165 SP = -1; // the Root <-> Root edge must be subtracted! … … 4574 4168 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4575 4169 Binder = Binder->next; 4576 SP ++; 4170 SP ++; 4577 4171 } 4578 4172 } … … 4581 4175 // start with root (push on fragment stack) 4582 4176 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4583 FragmentSearch.FragmentSet->clear(); 4177 FragmentSearch.FragmentSet->clear(); 4584 4178 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4585 4179 // prepare the subset and call the generator 4586 4180 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4587 4181 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4588 4182 4589 4183 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4590 4184 4591 4185 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4592 4186 } else { … … 4597 4191 // remove root from stack 4598 4192 *out << Verbose(0) << "Removing root again from stack." << endl; 4599 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4193 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4600 4194 4601 4195 // free'ing the bonds lists … … 4616 4210 } 4617 4211 4618 // return list 4212 // return list 4619 4213 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4620 4214 return (FragmentSearch.FragmentCounter - Counter); … … 4647 4241 // remove bonds that are beyond bonddistance 4648 4242 for(int i=NDIM;i--;) 4649 Translationvector.x[i] = 0.; 4243 Translationvector.x[i] = 0.; 4650 4244 // scan all bonds 4651 4245 Binder = first; … … 4694 4288 } 4695 4289 } 4696 // re-add bond 4290 // re-add bond 4697 4291 link(Binder, OtherBinder); 4698 4292 } else { … … 4748 4342 IteratorB++; 4749 4343 } // end of while loop 4750 }// end of check in case of equal sizes 4344 }// end of check in case of equal sizes 4751 4345 } 4752 4346 return false; // if we reach this point, they are equal … … 4792 4386 * \param graph1 first (dest) graph 4793 4387 * \param graph2 second (source) graph 4794 * \param *counter keyset counter that gets increased 4388 * \param *counter keyset counter that gets increased 4795 4389 */ 4796 4390 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 4837 4431 int RootKeyNr, RootNr; 4838 4432 struct UniqueFragments FragmentSearch; 4839 4433 4840 4434 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4841 4435 … … 4860 4454 Walker = Walker->next; 4861 4455 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4862 } 4456 } 4863 4457 4864 4458 // 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 … … 4874 4468 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4875 4469 // *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; 4876 //} else 4470 //} else 4877 4471 { 4878 4472 // increase adaptive order by one 4879 4473 Walker->GetTrueFather()->AdaptiveOrder++; 4880 4474 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4881 4475 4882 4476 // initialise Order-dependent entries of UniqueFragments structure 4883 4477 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 4886 4480 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4887 4481 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4888 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4482 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4889 4483 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4890 4484 FragmentSearch.BondsPerSPCount[i] = 0; 4891 } 4892 4485 } 4486 4893 4487 // allocate memory for all lower level orders in this 1D-array of ptrs 4894 4488 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 4896 4490 for (int i=0;i<NumLevels;i++) 4897 4491 FragmentLowerOrdersList[RootNr][i] = NULL; 4898 4492 4899 4493 // create top order where nothing is reduced 4900 4494 *out << Verbose(0) << "==============================================================================================================" << endl; 4901 4495 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4902 4496 4903 4497 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4904 4498 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 4913 4507 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4914 4508 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4915 4509 4916 4510 // if ((NumLevels >> 1) > 0) { 4917 4511 // // create lower order fragments … … 4920 4514 // 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) 4921 4515 // // step down to next order at (virtual) boundary of powers of 2 in array 4922 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4516 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4923 4517 // Order--; 4924 4518 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 4927 4521 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4928 4522 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4929 // 4523 // 4930 4524 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4931 4525 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 4958 4552 RootStack.push_back(RootKeyNr); // put back on stack 4959 4553 RootNr++; 4960 4554 4961 4555 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4962 4556 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 4964 4558 delete(FragmentSearch.BondsPerSPList[2*i]); 4965 4559 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4966 } 4560 } 4967 4561 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4968 4562 } … … 4975 4569 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4976 4570 delete(FragmentSearch.FragmentSet); 4977 4978 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4571 4572 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4979 4573 // 5433222211111111 4980 4574 // 43221111 … … 4996 4590 RootKeyNr = RootStack.front(); 4997 4591 RootStack.pop_front(); 4998 Walker = FindAtom(RootKeyNr); 4592 Walker = FindAtom(RootKeyNr); 4999 4593 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 5000 4594 for(int i=0;i<NumLevels;i++) { … … 5009 4603 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 5010 4604 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 5011 4605 5012 4606 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 5013 4607 }; … … 5043 4637 atom *Walker = NULL; 5044 4638 bool result = true; // status of comparison 5045 5046 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4639 4640 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5047 4641 /// first count both their atoms and elements and update lists thereby ... 5048 4642 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 5091 4685 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 5092 4686 *out << Verbose(4) << "Centers of gravity don't match." << endl; 5093 result = false; 5094 } 5095 } 5096 4687 result = false; 4688 } 4689 } 4690 5097 4691 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 5098 4692 if (result) { … … 5110 4704 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 5111 4705 } 5112 4706 5113 4707 /// ... sort each list (using heapsort (o(N log N)) from GSL) 5114 4708 *out << Verbose(5) << "Sorting distances" << endl; … … 5121 4715 for(int i=AtomCount;i--;) 5122 4716 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 5123 4717 5124 4718 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 5125 4719 *out << Verbose(4) << "Comparing distances" << endl; … … 5132 4726 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 5133 4727 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 5134 4728 5135 4729 /// free memory 5136 4730 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 5140 4734 result = false; 5141 4735 } 5142 } 4736 } 5143 4737 /// return pointer to map if all distances were below \a threshold 5144 4738 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 5149 4743 *out << Verbose(3) << "Result: Not equal." << endl; 5150 4744 return NULL; 5151 } 4745 } 5152 4746 }; 5153 4747 … … 5204 4798 * \param *output output stream of temperature file 5205 4799 * \return file written (true), failure on writing file (false) 5206 */ 4800 */ 5207 4801 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 5208 4802 { … … 5212 4806 if (output == NULL) 5213 4807 return false; 5214 else 4808 else 5215 4809 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 5216 4810 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.