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