Changes in molecuilder/src/molecules.cpp [d01f4d:848729]
- File:
-
- 1 edited
-
molecuilder/src/molecules.cpp (modified) (211 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/molecules.cpp
-
Property mode
changed from
100644to100755
rd01f4d r848729 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 * \param config structure with config::Deltat, config::IsAngstroem, config::DoConstrained1482 1016 * \param delta_t time step width in atomic units 1483 1017 * \param IsAngstroem whether coordinates are in angstroem (true) or bohrradius (false) 1484 * \param DoConstrained whether we perform a constrained (>0, target step in molecule::trajectories) or unconstrained (0) molecular dynamics, \sa molecule::MinimiseConstrainedPotential()1485 1018 * \return true - file found and parsed, false - file not found or imparsable 1486 * \todo This is not yet checked if it is correctly working with DoConstrained set to true.1487 */ 1488 bool molecule::VerletForceIntegration(ofstream *out, char *file, config &configuration) 1489 { 1019 */ 1020 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1021 { 1022 element *runner = elemente->start; 1490 1023 atom *walker = NULL; 1491 1024 int AtomNo; … … 1493 1026 string token; 1494 1027 stringstream item; 1495 double a, IonMass , Vector[NDIM], ConstrainedPotentialEnergy, ActualTemp;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 (configuration.DoConstrainedMD) { 1526 // calculate forces and potential 1527 atom **PermutationMap = NULL; 1528 ConstrainedPotentialEnergy = MinimiseConstrainedPotential(out, PermutationMap,configuration.DoConstrainedMD, 0, configuration.GetIsAngstroem()); 1529 EvaluateConstrainedForces(out, configuration.DoConstrainedMD, 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 walker = start; 1535 while (walker->next != end) { // go through every atom of this element 1536 walker = walker->next; 1537 //a = configuration.Deltat*0.5/walker->type->mass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1538 // check size of vectors 1539 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1540 //out << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1541 Trajectories[walker].R.resize(MDSteps+10); 1542 Trajectories[walker].U.resize(MDSteps+10); 1543 Trajectories[walker].F.resize(MDSteps+10); 1544 } 1545 1546 // Update R (and F) 1547 for (int d=0; d<NDIM; d++) { 1548 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][walker->nr][d+5]*(configuration.GetIsAngstroem() ? AtomicLengthToAngstroem : 1.); 1549 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1550 Trajectories[walker].R.at(MDSteps).x[d] += configuration.Deltat*(Trajectories[walker].U.at(MDSteps-1).x[d]); // s(t) = s(0) + v * deltat + 1/2 a * deltat^2 1551 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*configuration.Deltat*configuration.Deltat*(Trajectories[walker].F.at(MDSteps).x[d]/walker->type->mass); // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1552 } 1553 // Update U 1554 for (int d=0; d<NDIM; d++) { 1555 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1556 Trajectories[walker].U.at(MDSteps).x[d] += configuration.Deltat * (Trajectories[walker].F.at(MDSteps).x[d]+Trajectories[walker].F.at(MDSteps-1).x[d]/walker->type->mass); // v = F/m * t 1557 } 1558 // out << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1559 // for (int d=0;d<NDIM;d++) 1560 // out << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1561 // out << ")\t("; 1562 // for (int d=0;d<NDIM;d++) 1563 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1564 // out << ")" << endl; 1565 // next atom 1566 } 1567 } 1568 // correct velocities (rather momenta) so that center of mass remains motionless 1569 for(int d=0;d<NDIM;d++) 1570 Vector[d] = 0.; 1571 IonMass = 0.; 1572 walker = start; 1573 while (walker->next != end) { // go through every atom 1574 walker = walker->next; 1575 IonMass += walker->type->mass; // sum up total mass 1576 for(int d=0;d<NDIM;d++) { 1577 Vector[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1578 } 1579 } 1580 for(int d=0;d<NDIM;d++) 1581 Vector[d] /= IonMass; 1582 ActualTemp = 0.; 1583 walker = start; 1584 while (walker->next != end) { // go through every atom of this element 1585 walker = walker->next; 1586 for(int d=0;d<NDIM;d++) { 1587 Trajectories[walker].U.at(MDSteps).x[d] -= Vector[d]; 1588 ActualTemp += 0.5 * walker->type->mass * Trajectories[walker].U.at(MDSteps).x[d] * Trajectories[walker].U.at(MDSteps).x[d]; 1589 } 1590 } 1591 Thermostats(configuration, ActualTemp, Berendsen); 1592 MDSteps++; 1593 1594 1595 // exit 1596 return true; 1597 }; 1598 1599 1600 /** Implementation of various thermostats. 1601 * All these thermostats apply an additional force which has the following forms: 1602 * -# Woodcock 1603 * \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$ 1604 * -# Gaussian 1605 * \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$ 1606 * -# Langevin 1607 * \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$ 1608 * -# Berendsen 1609 * \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$ 1610 * -# Nose-Hoover 1611 * \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$ 1612 * These Thermostats either simply rescale the velocities, thus this function should be called after ion velocities have been updated, and/or 1613 * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified 1614 * belatedly and the constraint force set. 1615 * \param *P Problem at hand 1616 * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover 1617 * \sa InitThermostat() 1618 */ 1619 void molecule::Thermostats(config &configuration, double ActualTemp, int Thermostat) 1620 { 1621 double ekin = 0.; 1622 double E = 0., G = 0.; 1623 double delta_alpha = 0.; 1624 double ScaleTempFactor; 1625 double sigma; 1626 double IonMass; 1627 int d; 1628 gsl_rng * r; 1629 const gsl_rng_type * T; 1630 double *U = NULL, *F = NULL, FConstraint[NDIM]; 1631 atom *walker = NULL; 1632 1633 // calculate scale configuration 1634 ScaleTempFactor = configuration.TargetTemp/ActualTemp; 1635 1636 // differentating between the various thermostats 1637 switch(Thermostat) { 1638 case None: 1639 cout << Verbose(2) << "Applying no thermostat..." << endl; 1640 break; 1641 case Woodcock: 1642 if ((configuration.ScaleTempStep > 0) && ((MDSteps-1) % configuration.ScaleTempStep == 0)) { 1643 cout << Verbose(2) << "Applying Woodcock thermostat..." << endl; 1059 runner = elemente->start; 1060 while (runner->next != elemente->end) { // go through every element 1061 runner = runner->next; 1062 IonMass = runner->mass; 1063 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1064 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1065 AtomNo = 0; 1644 1066 walker = start; 1645 1067 while (walker->next != end) { // go through every atom of this element 1646 1068 walker = walker->next; 1647 IonMass = walker->type->mass; 1648 U = Trajectories[walker].U.at(MDSteps).x; 1649 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1650 for (d=0; d<NDIM; d++) { 1651 U[d] *= sqrt(ScaleTempFactor); 1652 ekin += 0.5*IonMass * U[d]*U[d]; 1069 if (walker->type == runner) { // if this atom fits to element 1070 // check size of vectors 1071 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1072 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1073 Trajectories[walker].R.resize(MDSteps+10); 1074 Trajectories[walker].U.resize(MDSteps+10); 1075 Trajectories[walker].F.resize(MDSteps+10); 1653 1076 } 1654 } 1655 } 1656 break; 1657 case Gaussian: 1658 cout << Verbose(2) << "Applying Gaussian thermostat..." << endl; 1659 walker = start; 1660 while (walker->next != end) { // go through every atom of this element 1661 walker = walker->next; 1662 IonMass = walker->type->mass; 1663 U = Trajectories[walker].U.at(MDSteps).x; 1664 F = Trajectories[walker].F.at(MDSteps).x; 1665 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1666 for (d=0; d<NDIM; d++) { 1667 G += U[d] * F[d]; 1668 E += U[d]*U[d]*IonMass; 1669 } 1670 } 1671 cout << Verbose(1) << "Gaussian Least Constraint constant is " << G/E << "." << endl; 1672 walker = start; 1673 while (walker->next != end) { // go through every atom of this element 1674 walker = walker->next; 1675 IonMass = walker->type->mass; 1676 U = Trajectories[walker].U.at(MDSteps).x; 1677 F = Trajectories[walker].F.at(MDSteps).x; 1678 if (walker->FixedIon == 0) // even FixedIon moves, only not by other's forces 1679 for (d=0; d<NDIM; d++) { 1680 FConstraint[d] = (G/E) * (U[d]*IonMass); 1681 U[d] += configuration.Deltat/IonMass * (FConstraint[d]); 1682 ekin += IonMass * U[d]*U[d]; 1683 } 1684 } 1685 break; 1686 case Langevin: 1687 cout << Verbose(2) << "Applying Langevin thermostat..." << endl; 1688 // init random number generator 1689 gsl_rng_env_setup(); 1690 T = gsl_rng_default; 1691 r = gsl_rng_alloc (T); 1692 // Go through each ion 1693 walker = start; 1694 while (walker->next != end) { // go through every atom of this element 1695 walker = walker->next; 1696 IonMass = walker->type->mass; 1697 sigma = sqrt(configuration.TargetTemp/IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime) 1698 U = Trajectories[walker].U.at(MDSteps).x; 1699 F = Trajectories[walker].F.at(MDSteps).x; 1700 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1701 // throw a dice to determine whether it gets hit by a heat bath particle 1702 if (((((rand()/(double)RAND_MAX))*configuration.TempFrequency) < 1.)) { 1703 cout << Verbose(3) << "Particle " << *walker << " was hit (sigma " << sigma << "): " << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << " -> "; 1704 // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis 1705 for (d=0; d<NDIM; d++) { 1706 U[d] = gsl_ran_gaussian (r, sigma); 1077 // 1. calculate x(t+\delta t) 1078 for (int d=0; d<NDIM; d++) { 1079 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1080 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1081 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1082 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 1707 1083 } 1708 cout << sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]) << endl; 1709 } 1710 for (d=0; d<NDIM; d++) 1711 ekin += 0.5*IonMass * U[d]*U[d]; 1712 } 1713 } 1714 break; 1715 case Berendsen: 1716 cout << Verbose(2) << "Applying Berendsen-VanGunsteren thermostat..." << endl; 1717 walker = start; 1718 while (walker->next != end) { // go through every atom of this element 1719 walker = walker->next; 1720 IonMass = walker->type->mass; 1721 U = Trajectories[walker].U.at(MDSteps).x; 1722 F = Trajectories[walker].F.at(MDSteps).x; 1723 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1724 for (d=0; d<NDIM; d++) { 1725 U[d] *= sqrt(1+(configuration.Deltat/configuration.TempFrequency)*(ScaleTempFactor-1)); 1726 ekin += 0.5*IonMass * U[d]*U[d]; 1084 // 2. Calculate v(t+\delta t) 1085 for (int d=0; d<NDIM; 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; 1088 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 // for (int d=0;d<NDIM;d++) 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1092 // cout << ")\t("; 1093 // for (int d=0;d<NDIM;d++) 1094 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1095 // cout << ")" << endl; 1096 // next atom 1097 AtomNo++; 1727 1098 } 1728 1099 } 1729 1100 } 1730 break; 1731 case NoseHoover: 1732 cout << Verbose(2) << "Applying Nose-Hoover thermostat..." << endl; 1733 // dynamically evolve alpha (the additional degree of freedom) 1734 delta_alpha = 0.; 1735 walker = start; 1736 while (walker->next != end) { // go through every atom of this element 1737 walker = walker->next; 1738 IonMass = walker->type->mass; 1739 U = Trajectories[walker].U.at(MDSteps).x; 1740 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1741 for (d=0; d<NDIM; d++) { 1742 delta_alpha += U[d]*U[d]*IonMass; 1743 } 1744 } 1745 } 1746 delta_alpha = (delta_alpha - (3.*AtomCount+1.) * configuration.TargetTemp)/(configuration.HooverMass*Units2Electronmass); 1747 configuration.alpha += delta_alpha*configuration.Deltat; 1748 cout << Verbose(3) << "alpha = " << delta_alpha << " * " << configuration.Deltat << " = " << configuration.alpha << "." << endl; 1749 // apply updated alpha as additional force 1750 walker = start; 1751 while (walker->next != end) { // go through every atom of this element 1752 walker = walker->next; 1753 IonMass = walker->type->mass; 1754 U = Trajectories[walker].U.at(MDSteps).x; 1755 if (walker->FixedIon == 0) { // even FixedIon moves, only not by other's forces 1756 for (d=0; d<NDIM; d++) { 1757 FConstraint[d] = - configuration.alpha * (U[d] * IonMass); 1758 U[d] += configuration.Deltat/IonMass * (FConstraint[d]); 1759 ekin += (0.5*IonMass) * U[d]*U[d]; 1760 } 1761 } 1762 } 1763 break; 1764 } 1765 cout << Verbose(1) << "Kinetic energy is " << ekin << "." << endl; 1766 }; 1767 1768 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1101 } 1102 } 1103 // // correct velocities (rather momenta) so that center of mass remains motionless 1104 // tmpvector.zero() 1105 // IonMass = 0.; 1106 // walker = start; 1107 // while (walker->next != end) { // go through every atom 1108 // walker = walker->next; 1109 // IonMass += walker->type->mass; // sum up total mass 1110 // for(int d=0;d<NDIM;d++) { 1111 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1112 // } 1113 // } 1114 // walker = start; 1115 // while (walker->next != end) { // go through every atom of this element 1116 // walker = walker->next; 1117 // for(int d=0;d<NDIM;d++) { 1118 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1119 // } 1120 // } 1121 MDSteps++; 1122 1123 1124 // exit 1125 return true; 1126 }; 1127 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1769 1129 * \param n[] alignment vector. 1770 1130 */ … … 1785 1145 ptr = ptr->next; 1786 1146 tmp = ptr->x.x[0]; 1787 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]; 1788 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1789 1149 for (int j=0;j<MDSteps;j++) { 1790 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1791 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]; 1792 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1793 1153 } 1794 } 1154 } 1795 1155 // rotate n vector 1796 1156 tmp = n->x[0]; … … 1800 1160 n->Output((ofstream *)&cout); 1801 1161 cout << endl; 1802 1162 1803 1163 // rotate on z-y plane 1804 1164 ptr = start; … … 1808 1168 ptr = ptr->next; 1809 1169 tmp = ptr->x.x[1]; 1810 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]; 1811 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1812 1172 for (int j=0;j<MDSteps;j++) { 1813 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1814 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]; 1815 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1816 1176 } 1817 } 1177 } 1818 1178 // rotate n vector (for consistency check) 1819 1179 tmp = n->x[1]; 1820 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1821 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1822 1182 1823 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1824 1184 n->Output((ofstream *)&cout); … … 1831 1191 * \return true - succeeded, false - atom not found in list 1832 1192 */ 1833 bool molecule::RemoveAtom(atom *pointer) 1834 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1835 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1836 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1837 1197 else 1838 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; 1839 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1840 1200 ElementCount--; … … 1846 1206 * \return true - succeeded, false - atom not found in list 1847 1207 */ 1848 bool molecule::CleanupMolecule() 1849 { 1850 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1851 1211 }; 1852 1212 … … 1862 1222 } else { 1863 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1864 return NULL; 1224 return NULL; 1865 1225 } 1866 1226 }; … … 1911 1271 struct lsq_params *par = (struct lsq_params *)params; 1912 1272 atom *ptr = par->mol->start; 1913 1273 1914 1274 // initialize vectors 1915 1275 a.x[0] = gsl_vector_get(x,0); … … 1941 1301 { 1942 1302 int np = 6; 1943 1303 1944 1304 const gsl_multimin_fminimizer_type *T = 1945 1305 gsl_multimin_fminimizer_nmsimplex; … … 1947 1307 gsl_vector *ss; 1948 1308 gsl_multimin_function minex_func; 1949 1309 1950 1310 size_t iter = 0, i; 1951 1311 int status; 1952 1312 double size; 1953 1313 1954 1314 /* Initial vertex size vector */ 1955 1315 ss = gsl_vector_alloc (np); 1956 1316 1957 1317 /* Set all step sizes to 1 */ 1958 1318 gsl_vector_set_all (ss, 1.0); 1959 1319 1960 1320 /* Starting point */ 1961 1321 par->x = gsl_vector_alloc (np); 1962 1322 par->mol = this; 1963 1323 1964 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1965 1325 gsl_vector_set (par->x, 1, 0.0); … … 1968 1328 gsl_vector_set (par->x, 4, 0.0); 1969 1329 gsl_vector_set (par->x, 5, 1.0); 1970 1330 1971 1331 /* Initialize method and iterate */ 1972 1332 minex_func.f = &LeastSquareDistance; 1973 1333 minex_func.n = np; 1974 1334 minex_func.params = (void *)par; 1975 1335 1976 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1977 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1978 1338 1979 1339 do 1980 1340 { 1981 1341 iter++; 1982 1342 status = gsl_multimin_fminimizer_iterate(s); 1983 1343 1984 1344 if (status) 1985 1345 break; 1986 1346 1987 1347 size = gsl_multimin_fminimizer_size (s); 1988 1348 status = gsl_multimin_test_size (size, 1e-2); 1989 1349 1990 1350 if (status == GSL_SUCCESS) 1991 1351 { 1992 1352 printf ("converged to minimum at\n"); 1993 1353 } 1994 1354 1995 1355 printf ("%5d ", (int)iter); 1996 1356 for (i = 0; i < (size_t)np; i++) … … 2001 1361 } 2002 1362 while (status == GSL_CONTINUE && iter < 100); 2003 1363 2004 1364 for (i=0;i<(size_t)np;i++) 2005 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 2018 1378 int ElementNo, AtomNo; 2019 1379 CountElements(); 2020 1380 2021 1381 if (out == NULL) { 2022 1382 return false; … … 2053 1413 int ElementNo, AtomNo; 2054 1414 CountElements(); 2055 1415 2056 1416 if (out == NULL) { 2057 1417 return false; … … 2100 1460 atom *Walker = start; 2101 1461 while (Walker->next != end) { 2102 Walker = Walker->next; 1462 Walker = Walker->next; 2103 1463 #ifdef ADDHYDROGEN 2104 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 2131 1491 int No = 0; 2132 1492 time_t now; 2133 1493 2134 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2135 1495 walker = start; … … 2158 1518 { 2159 1519 atom *walker = NULL; 2160 int No = 0;1520 int AtomNo = 0, ElementNo; 2161 1521 time_t now; 2162 1522 element *runner = NULL; 1523 2163 1524 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 2164 1525 walker = start; 2165 1526 while (walker->next != end) { // go through every atom and count 2166 1527 walker = walker->next; 2167 No++;1528 AtomNo++; 2168 1529 } 2169 1530 if (out != NULL) { 2170 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 2171 walker = start; 2172 while (walker->next != end) { // go through every atom of this element 2173 walker = walker->next; 2174 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 } 2175 1546 } 2176 1547 return true; … … 2203 1574 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 2204 1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 2205 NoNonHydrogen++; 1576 NoNonHydrogen++; 2206 1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 2207 1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 2211 1582 } 2212 1583 } else 2213 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 2214 1585 } 2215 1586 }; … … 2223 1594 ElementsInMolecule[i] = 0; 2224 1595 ElementCount = 0; 2225 1596 2226 1597 atom *walker = start; 2227 1598 while (walker->next != end) { … … 2259 1630 Binder = Binder->next; 2260 1631 if (Binder->Cyclic) 2261 No++; 1632 No++; 2262 1633 } 2263 1634 delete(BackEdgeStack); … … 2317 1688 2318 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. 2319 1738 * Generally, we use the CSD approach to bond recognition, that is the the distance 2320 1739 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 2321 * a threshold t = 0.4 Angstroem. 1740 * a threshold t = 0.4 Angstroem. 2322 1741 * To make it O(N log N) the function uses the linked-cell technique as follows: 2323 1742 * The procedure is step-wise: … … 2336 1755 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 2337 1756 { 1757 2338 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 2339 1759 int No, NoBonds, CandidateBondNo; … … 2344 1764 Vector x; 2345 1765 int FalseBondDegree = 0; 2346 1766 2347 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 2348 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 2351 1771 cleanup(first,last); 2352 1772 } 2353 1773 2354 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 2355 1775 CountAtoms(out); … … 2370 1790 for (int i=NumberCells;i--;) 2371 1791 CellList[i] = NULL; 2372 1792 2373 1793 // 2b. put all atoms into its corresponding list 2374 1794 Walker = start; … … 2391 1811 if (CellList[index] == NULL) // allocate molecule if not done 2392 1812 CellList[index] = new molecule(elemente); 2393 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 2394 //*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; 2395 1815 } 2396 1816 //for (int i=0;i<NumberCells;i++) 2397 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 2398 1818 1819 2399 1820 // 3a. go through every cell 2400 1821 for (N[0]=divisor[0];N[0]--;) … … 2409 1830 Walker = Walker->next; 2410 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 2411 // 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 2412 1833 for (n[0]=-1;n[0]<=1;n[0]++) 2413 1834 for (n[1]=-1;n[1]<=1;n[1]++) … … 2441 1862 } 2442 1863 } 1864 1865 1866 2443 1867 // 4. free the cell again 2444 1868 for (int i=NumberCells;i--;) … … 2447 1871 } 2448 1872 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 2449 1873 2450 1874 // create the adjacency list per atom 2451 1875 CreateListOfBondsPerAtom(out); 2452 1876 2453 1877 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 2454 1878 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 2499 1923 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 2500 1924 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 2501 1925 2502 1926 // output bonds for debugging (if bond chain list was correctly installed) 2503 1927 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 2509 1933 *out << endl; 2510 1934 } else 2511 *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; 2512 1936 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2513 1937 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2514 }; 1938 1939 }; 1940 1941 2515 1942 2516 1943 /** Performs a Depth-First search on this molecule. … … 2533 1960 bond *Binder = NULL; 2534 1961 bool BackStepping = false; 2535 1962 2536 1963 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2537 1964 2538 1965 ResetAllBondsToUnused(); 2539 1966 ResetAllAtomNumbers(); … … 2548 1975 LeafWalker->Leaf = new molecule(elemente); 2549 1976 LeafWalker->Leaf->AddCopyAtom(Root); 2550 1977 2551 1978 OldGraphNr = CurrentGraphNr; 2552 1979 Walker = Root; … … 2559 1986 AtomStack->Push(Walker); 2560 1987 CurrentGraphNr++; 2561 } 1988 } 2562 1989 do { // (3) if Walker has no unused egdes, go to (5) 2563 1990 BackStepping = false; // reset backstepping flag for (8) … … 2593 2020 Binder = NULL; 2594 2021 } while (1); // (2) 2595 2022 2596 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! 2597 2024 if ((Walker == Root) && (Binder == NULL)) 2598 2025 break; 2599 2600 // (5) if Ancestor of Walker is ... 2026 2027 // (5) if Ancestor of Walker is ... 2601 2028 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2602 2029 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2641 2068 } while (OtherAtom != Walker); 2642 2069 ComponentNumber++; 2643 2070 2644 2071 // (11) Root is separation vertex, set Walker to Root and go to (4) 2645 2072 Walker = Root; … … 2654 2081 2655 2082 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2656 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2083 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2657 2084 LeafWalker->Leaf->Output(out); 2658 2085 *out << endl; … … 2662 2089 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2663 2090 if (Root->GraphNr != -1) // if already discovered, step on 2664 Root = Root->next; 2091 Root = Root->next; 2665 2092 } 2666 2093 } … … 2684 2111 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2685 2112 } 2686 2113 2687 2114 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2688 2115 Binder = first; … … 2695 2122 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2696 2123 OutputComponentNumber(out, Binder->rightatom); 2697 *out << ">." << endl; 2124 *out << ">." << endl; 2698 2125 if (Binder->Cyclic) // cyclic ?? 2699 2126 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2710 2137 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2711 2138 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2712 * as cyclic and print out the cycles. 2139 * as cyclic and print out the cycles. 2713 2140 * \param *out output stream for debugging 2714 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! … … 2721 2148 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2722 2149 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2723 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 2724 2151 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2725 2152 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2733 2160 ColorList[i] = white; 2734 2161 } 2735 2162 2736 2163 *out << Verbose(1) << "Back edge list - "; 2737 2164 BackEdgeStack->Output(out); 2738 2165 2739 2166 *out << Verbose(1) << "Analysing cycles ... " << endl; 2740 2167 NumCycles = 0; … … 2742 2169 BackEdge = BackEdgeStack->PopFirst(); 2743 2170 // this is the target 2744 Root = BackEdge->leftatom; 2171 Root = BackEdge->leftatom; 2745 2172 // this is the source point 2746 Walker = BackEdge->rightatom; 2173 Walker = BackEdge->rightatom; 2747 2174 ShortestPathList[Walker->nr] = 0; 2748 2175 BFSStack->ClearStack(); // start with empty BFS stack … … 2758 2185 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2759 2186 OtherAtom = Binder->GetOtherAtom(Walker); 2760 #ifdef ADDHYDROGEN 2187 #ifdef ADDHYDROGEN 2761 2188 if (OtherAtom->type->Z != 1) { 2762 2189 #endif … … 2767 2194 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2768 2195 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2769 *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; 2770 2197 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2771 2198 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2777 2204 if (OtherAtom == Root) 2778 2205 break; 2779 #ifdef ADDHYDROGEN 2206 #ifdef ADDHYDROGEN 2780 2207 } else { 2781 2208 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2815 2242 } 2816 2243 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2817 2244 2818 2245 if (OtherAtom == Root) { 2819 2246 // now climb back the predecessor list and thus find the cycle members … … 2843 2270 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2844 2271 } 2845 2272 2846 2273 // now clean the lists 2847 2274 while (!TouchedStack->IsEmpty()){ … … 2853 2280 } 2854 2281 if (MinRingSize != -1) { 2855 // go over all atoms 2282 // go over all atoms 2856 2283 Root = start; 2857 2284 while(Root->next != end) { 2858 2285 Root = Root->next; 2859 2286 2860 2287 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2861 2288 Walker = Root; … … 2894 2321 } 2895 2322 ColorList[Walker->nr] = black; 2896 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2323 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2897 2324 } 2898 2325 2899 2326 // now clean the lists 2900 2327 while (!TouchedStack->IsEmpty()){ … … 2945 2372 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2946 2373 { 2947 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2374 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2948 2375 *out << vertex->ComponentNr[i] << " "; 2949 2376 }; … … 3023 2450 { 3024 2451 int c = 0; 3025 int FragmentCount; 2452 int FragmentCount; 3026 2453 // get maximum bond degree 3027 2454 atom *Walker = start; … … 3033 2460 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 3034 2461 return FragmentCount; 3035 }; 2462 }; 3036 2463 3037 2464 /** Scans a single line for number and puts them into \a KeySet. 3038 2465 * \param *out output stream for debugging 3039 2466 * \param *buffer buffer to scan 3040 * \param &CurrentSet filled KeySet on return 2467 * \param &CurrentSet filled KeySet on return 3041 2468 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 3042 2469 */ … … 3046 2473 int AtomNr; 3047 2474 int status = 0; 3048 2475 3049 2476 line.str(buffer); 3050 2477 while (!line.eof()) { … … 3082 2509 double TEFactor; 3083 2510 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 3084 2511 3085 2512 if (FragmentList == NULL) { // check list pointer 3086 2513 FragmentList = new Graph; 3087 2514 } 3088 2515 3089 2516 // 1st pass: open file and read 3090 2517 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 3115 2542 status = false; 3116 2543 } 3117 2544 3118 2545 // 2nd pass: open TEFactors file and read 3119 2546 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 3127 2554 InputFile >> TEFactor; 3128 2555 (*runner).second.second = TEFactor; 3129 *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; 3130 2557 } else { 3131 2558 status = false; … … 3168 2595 if(output != NULL) { 3169 2596 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 3170 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++) { 3171 2598 if (sprinter != (*runner).first.begin()) 3172 2599 output << "\t"; … … 3234 2661 status = false; 3235 2662 } 3236 2663 3237 2664 return status; 3238 2665 }; … … 3243 2670 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 3244 2671 * \return true - structure is equal, false - not equivalence 3245 */ 2672 */ 3246 2673 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 3247 2674 { … … 3250 2677 bool status = true; 3251 2678 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3252 2679 3253 2680 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 3254 2681 File.open(filename.str().c_str(), ios::out); … … 3309 2736 *out << endl; 3310 2737 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 3311 2738 3312 2739 return status; 3313 2740 }; … … 3331 2758 for(int i=AtomCount;i--;) 3332 2759 AtomMask[i] = false; 3333 2760 3334 2761 if (Order < 0) { // adaptive increase of BondOrder per site 3335 2762 if (AtomMask[AtomCount] == true) // break after one step … … 3371 2798 line >> ws >> Value; // skip time entry 3372 2799 line >> ws >> Value; 3373 No -= 1; // indices start at 1 in file, not 0 2800 No -= 1; // indices start at 1 in file, not 0 3374 2801 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 3375 2802 … … 3380 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 3381 2808 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 3382 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2809 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 3383 2810 if (!InsertedElement.second) { // this root is already present 3384 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 3385 //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) 3386 2813 { // if value is smaller, update value and order 3387 2814 (*PresentItem).second.first = fabs(Value); … … 3421 2848 Walker = FindAtom(No); 3422 2849 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 3423 *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; 3424 2851 AtomMask[No] = true; 3425 2852 status = true; 3426 2853 //} else 3427 //*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; 3428 2855 } 3429 2856 // close and done … … 3459 2886 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 3460 2887 status = true; 3461 2888 3462 2889 if (!status) { 3463 2890 if (Order == 0) … … 3467 2894 } 3468 2895 } 3469 2896 3470 2897 // print atom mask for debugging 3471 2898 *out << " "; … … 3476 2903 *out << (AtomMask[i] ? "t" : "f"); 3477 2904 *out << endl; 3478 2905 3479 2906 return status; 3480 2907 }; … … 3490 2917 int AtomNo = 0; 3491 2918 atom *Walker = NULL; 3492 2919 3493 2920 if (SortIndex != NULL) { 3494 2921 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 3548 2975 atom **ListOfAtoms = NULL; 3549 2976 atom ***ListOfLocalAtoms = NULL; 3550 bool *AtomMask = NULL; 3551 2977 bool *AtomMask = NULL; 2978 3552 2979 *out << endl; 3553 2980 #ifdef ADDHYDROGEN … … 3558 2985 3559 2986 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3560 2987 3561 2988 // ===== 1. Check whether bond structure is same as stored in files ==== 3562 2989 3563 2990 // fill the adjacency list 3564 2991 CreateListOfBondsPerAtom(out); … … 3566 2993 // create lookup table for Atom::nr 3567 2994 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3568 2995 3569 2996 // === compare it with adjacency file === 3570 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2997 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3571 2998 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3572 2999 … … 3582 3009 while (MolecularWalker->next != NULL) { 3583 3010 MolecularWalker = MolecularWalker->next; 3584 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3585 3011 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3586 3012 // // check the list of local atoms for debugging … … 3591 3017 // else 3592 3018 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3019 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3593 3020 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3021 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3594 3022 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3023 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3595 3024 delete(LocalBackEdgeStack); 3596 3025 } 3597 3026 3598 3027 // ===== 3. if structure still valid, parse key set file and others ===== 3599 3028 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 3601 3030 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3602 3031 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3603 3604 // =================================== Begin of FRAGMENTATION =============================== 3605 // ===== 6a. assign each keyset to its respective subgraph ===== 3032 3033 // =================================== Begin of FRAGMENTATION =============================== 3034 // ===== 6a. assign each keyset to its respective subgraph ===== 3606 3035 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3607 3036 … … 3614 3043 FragmentationToDo = FragmentationToDo || CheckOrder; 3615 3044 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3616 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3045 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3617 3046 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3618 3047 … … 3623 3052 MolecularWalker = MolecularWalker->next; 3624 3053 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3625 // output ListOfBondsPerAtom for debugging 3626 MolecularWalker->Leaf->OutputListOfBonds(out); 3054 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3627 3055 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3628 3629 3056 // call BOSSANOVA method 3630 3057 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; … … 3640 3067 delete(ParsedFragmentList); 3641 3068 delete[](MinimumRingSize); 3642 3069 3643 3070 3644 3071 // ==================================== End of FRAGMENTATION ============================================ … … 3646 3073 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3647 3074 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3648 3075 3649 3076 // free subgraph memory again 3650 3077 FragmentCounter = 0; … … 3671 3098 } 3672 3099 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3673 3100 3674 3101 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3675 3102 if (BondFragments->NumberOfMolecules != 0) { 3676 3103 // create the SortIndex from BFS labels to order in the config file 3677 3104 CreateMappingLabelsToConfigSequence(out, SortIndex); 3678 3105 3679 3106 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3680 if (BondFragments->OutputConfigForListOfFragments(out, FRAGMENTPREFIX, configuration, SortIndex, true, true))3107 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3681 3108 *out << Verbose(1) << "All configs written." << endl; 3682 3109 else 3683 3110 *out << Verbose(1) << "Some config writing failed." << endl; 3684 3111 3685 3112 // store force index reference file 3686 3113 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3687 3688 // store keysets file 3114 3115 // store keysets file 3689 3116 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3690 3691 // store Adjacency file 3117 3118 // store Adjacency file 3692 3119 StoreAdjacencyToFile(out, configuration->configpath); 3693 3120 3694 3121 // store Hydrogen saturation correction file 3695 3122 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3696 3123 3697 3124 // store adaptive orders into file 3698 3125 StoreOrderAtSiteFile(out, configuration->configpath); 3699 3126 3700 3127 // restore orbital and Stop values 3701 3128 CalculateOrbitals(*configuration); 3702 3129 3703 3130 // free memory for bond part 3704 3131 *out << Verbose(1) << "Freeing bond memory" << endl; 3705 3132 delete(FragmentList); // remove bond molecule from memory 3706 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3133 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3707 3134 } else 3708 3135 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3709 //} else 3136 //} else 3710 3137 // *out << Verbose(1) << "No fragments to store." << endl; 3711 3138 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3733 3160 atom *Walker = NULL, *OtherAtom = NULL; 3734 3161 ReferenceStack->Push(Binder); 3735 3162 3736 3163 do { // go through all bonds and push local ones 3737 3164 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3738 if (Walker == NULL) // if this Walker exists in the subgraph ...3739 continue;3740 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds3741 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3742 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3743 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3744 break;3745 }3746 }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 } 3747 3174 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3175 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3748 3176 ReferenceStack->Push(Binder); 3749 3177 } while (FirstBond != Binder); 3750 3178 3751 3179 return status; 3752 3180 }; … … 3824 3252 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3825 3253 Walker->MaxOrder = MaxArray[Walker->nr]; 3826 *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; 3827 3255 } 3828 3256 file.close(); … … 3835 3263 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3836 3264 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3837 3265 3838 3266 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3839 3267 return status; … … 3893 3321 Walker = start; 3894 3322 while (Walker->next != end) { 3895 Walker = Walker->next; 3323 Walker = Walker->next; 3896 3324 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3897 3325 TotalDegree = 0; … … 3901 3329 } 3902 3330 *out << " -- TotalDegree: " << TotalDegree << endl; 3903 } 3331 } 3904 3332 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3905 3333 }; … … 3907 3335 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3908 3336 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3909 * white and putting into queue. 3337 * white and putting into queue. 3910 3338 * \param *out output stream for debugging 3911 3339 * \param *Mol Molecule class to add atoms to … … 3916 3344 * \param BondOrder maximum distance for vertices to add 3917 3345 * \param IsAngstroem lengths are in angstroem or bohrradii 3918 */ 3346 */ 3919 3347 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3920 3348 { … … 3942 3370 } 3943 3371 ShortestPathList[Root->nr] = 0; 3944 3372 3945 3373 // and go on ... Queue always contains all lightgray vertices 3946 3374 while (!AtomStack->IsEmpty()) { … … 3950 3378 // followed by n+1 till top of stack. 3951 3379 Walker = AtomStack->PopFirst(); // pop oldest added 3952 *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; 3953 3381 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3954 3382 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3957 3385 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3958 3386 if (ColorList[OtherAtom->nr] == white) { 3959 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) 3960 3388 ColorList[OtherAtom->nr] = lightgray; 3961 3389 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3962 3390 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3963 *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; 3964 3392 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3965 3393 *out << Verbose(3); … … 3999 3427 } else { 4000 3428 #ifdef ADDHYDROGEN 4001 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); 4002 3431 #endif 4003 3432 } … … 4008 3437 // This has to be a cyclic bond, check whether it's present ... 4009 3438 if (AddedBondList[Binder->nr] == NULL) { 4010 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3439 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 4011 3440 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 4012 3441 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 4014 3443 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 4015 3444 #ifdef ADDHYDROGEN 4016 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); 4017 3447 #endif 4018 3448 } … … 4022 3452 } 4023 3453 ColorList[Walker->nr] = black; 4024 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3454 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 4025 3455 } 4026 3456 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 4046 3476 4047 3477 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 4048 3478 4049 3479 // reset parent list 4050 3480 *out << Verbose(3) << "Resetting ParentList." << endl; 4051 3481 for (int i=Father->AtomCount;i--;) 4052 3482 ParentList[i] = NULL; 4053 3483 4054 3484 // fill parent list with sons 4055 3485 *out << Verbose(3) << "Filling Parent List." << endl; … … 4092 3522 * \param *&Leaf KeySet to look through 4093 3523 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 4094 * \param index of the atom suggested for removal 3524 * \param index of the atom suggested for removal 4095 3525 */ 4096 3526 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 4098 3528 atom *Runner = NULL; 4099 3529 int SP, Removal; 4100 3530 4101 3531 *out << Verbose(2) << "Looking for removal candidate." << endl; 4102 3532 SP = -1; //0; // not -1, so that Root is never removed … … 4116 3546 /** Stores a fragment from \a KeySet into \a molecule. 4117 3547 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 4118 * molecule and adds missing hydrogen where bonds were cut. 3548 * molecule and adds missing hydrogen where bonds were cut. 4119 3549 * \param *out output stream for debugging messages 4120 * \param &Leaflet pointer to KeySet structure 3550 * \param &Leaflet pointer to KeySet structure 4121 3551 * \param IsAngstroem whether we have Ansgtroem or bohrradius 4122 3552 * \return pointer to constructed molecule … … 4129 3559 bool LonelyFlag = false; 4130 3560 int size; 4131 3561 4132 3562 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 4133 3563 4134 3564 Leaf->BondDistance = BondDistance; 4135 3565 for(int i=NDIM*2;i--;) 4136 Leaf->cell_size[i] = cell_size[i]; 3566 Leaf->cell_size[i] = cell_size[i]; 4137 3567 4138 3568 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 4147 3577 size++; 4148 3578 } 4149 3579 4150 3580 // create the bonds between all: Make it an induced subgraph and add hydrogen 4151 3581 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 4157 3587 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 4158 3588 // create all bonds 4159 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 4160 3590 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 4161 3591 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 4162 3592 if (SonList[OtherFather->nr] != NULL) { 4163 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3593 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 4164 3594 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 4165 3595 // *out << Verbose(3) << "Adding Bond: "; 4166 // *out << 3596 // *out << 4167 3597 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 4168 3598 // *out << "." << endl; 4169 3599 //NumBonds[Runner->nr]++; 4170 } else { 3600 } else { 4171 3601 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 4172 3602 } 4173 3603 LonelyFlag = false; 4174 3604 } else { 4175 // *out << ", who has no son in this fragment molecule." << endl; 3605 // *out << ", who has no son in this fragment molecule." << endl; 4176 3606 #ifdef ADDHYDROGEN 4177 3607 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 4178 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); 4179 3610 #endif 4180 3611 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; … … 4190 3621 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 4191 3622 Runner = Runner->next; 4192 #endif 3623 #endif 4193 3624 } 4194 3625 Leaf->CreateListOfBondsPerAtom(out); … … 4223 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 4224 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! 4225 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3656 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 4226 3657 MoleculeListClass *FragmentList = NULL; 4227 3658 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 4273 3704 // clear snake stack 4274 3705 SnakeStack->ClearStack(); 4275 //SnakeStack->TestImplementation(out, start->next); 3706 //SnakeStack->TestImplementation(out, start->next); 4276 3707 4277 3708 ///// INNER LOOP //////////// … … 4294 3725 } 4295 3726 if (ShortestPathList[Walker->nr] == -1) { 4296 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3727 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 4297 3728 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 4298 3729 } … … 4332 3763 OtherAtom = Binder->GetOtherAtom(Walker); 4333 3764 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 4334 *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; 4335 3766 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 4336 3767 } else { // otherwise check its colour and element 4337 3768 if ( 4338 3769 #ifdef ADDHYDROGEN 4339 (OtherAtom->type->Z != 1) && 3770 (OtherAtom->type->Z != 1) && 4340 3771 #endif 4341 3772 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 4347 3778 //} else { 4348 3779 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 4349 //} 3780 //} 4350 3781 Walker = OtherAtom; 4351 3782 break; 4352 3783 } else { 4353 if (OtherAtom->type->Z == 1) 3784 if (OtherAtom->type->Z == 1) 4354 3785 *out << "Links to a hydrogen atom." << endl; 4355 else 3786 else 4356 3787 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 4357 3788 } … … 4363 3794 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 4364 3795 } 4365 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3796 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 4366 3797 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 4367 3798 ColorVertexList[Walker->nr] = black; … … 4370 3801 } 4371 3802 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 4372 *out << Verbose(2) << "Inner Looping is finished." << endl; 3803 *out << Verbose(2) << "Inner Looping is finished." << endl; 4373 3804 4374 3805 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 4386 3817 } 4387 3818 } 4388 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3819 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 4389 3820 4390 3821 // copy together 4391 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3822 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 4392 3823 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 4393 3824 RunningIndex = 0; … … 4460 3891 4461 3892 NumCombinations = 1 << SetDimension; 4462 3893 4463 3894 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 4464 3895 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 4465 3896 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 4466 3897 4467 3898 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 4468 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; 4469 3900 4470 // initialised touched list (stores added atoms on this level) 3901 // initialised touched list (stores added atoms on this level) 4471 3902 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 4472 3903 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 4473 3904 TouchedList[TouchedIndex] = -1; 4474 3905 TouchedIndex = 0; 4475 3906 4476 3907 // create every possible combination of the endpieces 4477 3908 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 4481 3912 for (int j=SetDimension;j--;) 4482 3913 bits += (i & (1 << j)) >> j; 4483 3914 4484 3915 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 4485 3916 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 4489 3920 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 4490 3921 if (bit) { // if bit is set, we add this bond partner 4491 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 4492 3923 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 4493 3924 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 4494 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3925 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 4495 3926 if (TestKeySetInsert.second) { 4496 3927 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 4505 3936 } 4506 3937 } 4507 4508 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 4509 3940 if (SpaceLeft > 0) { 4510 3941 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 4534 3965 } 4535 3966 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 4536 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3967 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 4537 3968 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 4538 3969 } … … 4543 3974 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 4544 3975 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4545 *out << (*runner) << " "; 3976 *out << (*runner) << " "; 4546 3977 *out << endl; 4547 3978 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 4551 3982 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 4552 3983 } 4553 3984 4554 3985 // --3-- remove all added items in this level from snake stack 4555 3986 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 4562 3993 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 4563 3994 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 4564 *out << (*runner) << " "; 3995 *out << (*runner) << " "; 4565 3996 *out << endl; 4566 3997 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 4569 4000 } 4570 4001 } 4571 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4002 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4572 4003 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 4573 4004 }; … … 4578 4009 * \return true - connected, false - disconnected 4579 4010 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 4580 */ 4011 */ 4581 4012 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 4582 4013 { … … 4584 4015 bool BondStatus = false; 4585 4016 int size; 4586 4017 4587 4018 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 4588 4019 *out << Verbose(2) << "Disconnected atom: "; 4589 4020 4590 4021 // count number of atoms in graph 4591 4022 size = 0; … … 4633 4064 * \param *out output stream for debugging 4634 4065 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 4635 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4066 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4636 4067 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4637 4068 * \return number of inserted fragments 4638 4069 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4639 4070 */ 4640 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) 4641 4072 { 4642 4073 int SP, AtomKeyNr; … … 4659 4090 FragmentSearch.BondsPerSPCount[i] = 0; 4660 4091 FragmentSearch.BondsPerSPCount[0] = 1; 4661 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4092 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4662 4093 add(Binder, FragmentSearch.BondsPerSPList[1]); 4663 4094 4664 4095 // do a BFS search to fill the SP lists and label the found vertices 4665 4096 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4666 4097 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4667 4098 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4668 // (EdgeinSPLevel) of this tree ... 4099 // (EdgeinSPLevel) of this tree ... 4669 4100 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4670 4101 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4719 4150 } 4720 4151 } 4721 4152 4722 4153 // outputting all list for debugging 4723 4154 *out << Verbose(0) << "Printing all found lists." << endl; … … 4728 4159 Binder = Binder->next; 4729 4160 *out << Verbose(2) << *Binder << endl; 4730 } 4731 } 4732 4161 } 4162 } 4163 4733 4164 // creating fragments with the found edge sets (may be done in reverse order, faster) 4734 4165 SP = -1; // the Root <-> Root edge must be subtracted! … … 4737 4168 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4738 4169 Binder = Binder->next; 4739 SP ++; 4170 SP ++; 4740 4171 } 4741 4172 } … … 4744 4175 // start with root (push on fragment stack) 4745 4176 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4746 FragmentSearch.FragmentSet->clear(); 4177 FragmentSearch.FragmentSet->clear(); 4747 4178 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4748 4179 // prepare the subset and call the generator 4749 4180 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4750 4181 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4751 4182 4752 4183 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4753 4184 4754 4185 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4755 4186 } else { … … 4760 4191 // remove root from stack 4761 4192 *out << Verbose(0) << "Removing root again from stack." << endl; 4762 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4193 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4763 4194 4764 4195 // free'ing the bonds lists … … 4779 4210 } 4780 4211 4781 // return list 4212 // return list 4782 4213 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4783 4214 return (FragmentSearch.FragmentCounter - Counter); … … 4810 4241 // remove bonds that are beyond bonddistance 4811 4242 for(int i=NDIM;i--;) 4812 Translationvector.x[i] = 0.; 4243 Translationvector.x[i] = 0.; 4813 4244 // scan all bonds 4814 4245 Binder = first; … … 4857 4288 } 4858 4289 } 4859 // re-add bond 4290 // re-add bond 4860 4291 link(Binder, OtherBinder); 4861 4292 } else { … … 4911 4342 IteratorB++; 4912 4343 } // end of while loop 4913 }// end of check in case of equal sizes 4344 }// end of check in case of equal sizes 4914 4345 } 4915 4346 return false; // if we reach this point, they are equal … … 4955 4386 * \param graph1 first (dest) graph 4956 4387 * \param graph2 second (source) graph 4957 * \param *counter keyset counter that gets increased 4388 * \param *counter keyset counter that gets increased 4958 4389 */ 4959 4390 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 5000 4431 int RootKeyNr, RootNr; 5001 4432 struct UniqueFragments FragmentSearch; 5002 4433 5003 4434 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 5004 4435 … … 5023 4454 Walker = Walker->next; 5024 4455 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 5025 } 4456 } 5026 4457 5027 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 … … 5037 4468 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 5038 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; 5039 //} else 4470 //} else 5040 4471 { 5041 4472 // increase adaptive order by one 5042 4473 Walker->GetTrueFather()->AdaptiveOrder++; 5043 4474 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 5044 4475 5045 4476 // initialise Order-dependent entries of UniqueFragments structure 5046 4477 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 5049 4480 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 5050 4481 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 5051 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 5052 4483 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 5053 4484 FragmentSearch.BondsPerSPCount[i] = 0; 5054 } 5055 4485 } 4486 5056 4487 // allocate memory for all lower level orders in this 1D-array of ptrs 5057 4488 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 5059 4490 for (int i=0;i<NumLevels;i++) 5060 4491 FragmentLowerOrdersList[RootNr][i] = NULL; 5061 4492 5062 4493 // create top order where nothing is reduced 5063 4494 *out << Verbose(0) << "==============================================================================================================" << endl; 5064 4495 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 5065 4496 5066 4497 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 5067 4498 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 5076 4507 // we don't have to dive into suborders! These keysets are all already created on lower orders! 5077 4508 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 5078 4509 5079 4510 // if ((NumLevels >> 1) > 0) { 5080 4511 // // create lower order fragments … … 5083 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) 5084 4515 // // step down to next order at (virtual) boundary of powers of 2 in array 5085 // 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)) 5086 4517 // Order--; 5087 4518 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 5090 4521 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 5091 4522 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 5092 // 4523 // 5093 4524 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 5094 4525 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 5121 4552 RootStack.push_back(RootKeyNr); // put back on stack 5122 4553 RootNr++; 5123 4554 5124 4555 // free Order-dependent entries of UniqueFragments structure for next loop cycle 5125 4556 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 5127 4558 delete(FragmentSearch.BondsPerSPList[2*i]); 5128 4559 delete(FragmentSearch.BondsPerSPList[2*i+1]); 5129 } 4560 } 5130 4561 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 5131 4562 } … … 5138 4569 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 5139 4570 delete(FragmentSearch.FragmentSet); 5140 5141 // 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) 5142 4573 // 5433222211111111 5143 4574 // 43221111 … … 5159 4590 RootKeyNr = RootStack.front(); 5160 4591 RootStack.pop_front(); 5161 Walker = FindAtom(RootKeyNr); 4592 Walker = FindAtom(RootKeyNr); 5162 4593 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 5163 4594 for(int i=0;i<NumLevels;i++) { … … 5172 4603 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 5173 4604 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 5174 4605 5175 4606 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 5176 4607 }; … … 5206 4637 atom *Walker = NULL; 5207 4638 bool result = true; // status of comparison 5208 5209 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4639 4640 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 5210 4641 /// first count both their atoms and elements and update lists thereby ... 5211 4642 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 5254 4685 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 5255 4686 *out << Verbose(4) << "Centers of gravity don't match." << endl; 5256 result = false; 5257 } 5258 } 5259 4687 result = false; 4688 } 4689 } 4690 5260 4691 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 5261 4692 if (result) { … … 5273 4704 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 5274 4705 } 5275 4706 5276 4707 /// ... sort each list (using heapsort (o(N log N)) from GSL) 5277 4708 *out << Verbose(5) << "Sorting distances" << endl; … … 5284 4715 for(int i=AtomCount;i--;) 5285 4716 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 5286 4717 5287 4718 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 5288 4719 *out << Verbose(4) << "Comparing distances" << endl; … … 5295 4726 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 5296 4727 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 5297 4728 5298 4729 /// free memory 5299 4730 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 5303 4734 result = false; 5304 4735 } 5305 } 4736 } 5306 4737 /// return pointer to map if all distances were below \a threshold 5307 4738 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 5312 4743 *out << Verbose(3) << "Result: Not equal." << endl; 5313 4744 return NULL; 5314 } 4745 } 5315 4746 }; 5316 4747 … … 5367 4798 * \param *output output stream of temperature file 5368 4799 * \return file written (true), failure on writing file (false) 5369 */ 4800 */ 5370 4801 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 5371 4802 { … … 5375 4806 if (output == NULL) 5376 4807 return false; 5377 else 4808 else 5378 4809 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 5379 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.
