Changes in molecuilder/src/molecules.cpp [f5d7e1:848729]
- File:
-
- 1 edited
-
molecuilder/src/molecules.cpp (modified) (209 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/molecules.cpp
-
Property mode
changed from
100644to100755
rf5d7e1 r848729 1 1 /** \file molecules.cpp 2 * 2 * 3 3 * Functions for the class molecule. 4 * 4 * 5 5 */ 6 6 … … 25 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 26 } 27 27 28 28 return sum; 29 29 }; … … 34 34 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 35 35 */ 36 molecule::molecule(periodentafel *teil) 37 { 36 molecule::molecule(periodentafel *teil) 37 { 38 38 // init atom chain list 39 start = new atom; 39 start = new atom; 40 40 end = new atom; 41 start->father = NULL; 41 start->father = NULL; 42 42 end->father = NULL; 43 43 link(start,end); … … 46 46 last = new bond(start, end, 1, -1); 47 47 link(first,last); 48 // other stuff 48 // other stuff 49 49 MDSteps = 0; 50 last_atom = 0; 50 last_atom = 0; 51 51 elemente = teil; 52 52 AtomCount = 0; … … 67 67 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 68 68 */ 69 molecule::~molecule() 69 molecule::~molecule() 70 70 { 71 71 if (ListOfBondsPerAtom != NULL) … … 78 78 delete(last); 79 79 delete(end); 80 delete(start); 80 delete(start); 81 81 }; 82 82 83 83 /** Adds given atom \a *pointer from molecule list. 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 85 85 * \param *pointer allocated and set atom 86 86 * \return true - succeeded, false - atom not found in list 87 87 */ 88 88 bool molecule::AddAtom(atom *pointer) 89 { 89 { 90 90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 91 pointer->sort = &pointer->nr; 92 92 pointer->nr = last_atom++; // increase number within molecule 93 93 AtomCount++; … … 106 106 return add(pointer, end); 107 107 } else 108 return false; 108 return false; 109 109 }; 110 110 … … 115 115 */ 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 { 117 { 118 118 if (pointer != NULL) { 119 119 atom *walker = new atom(); … … 122 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 124 walker->sort = &walker->nr; 125 125 walker->nr = last_atom++; // increase number within molecule 126 126 walker->father = pointer; //->GetTrueFather(); … … 133 133 return walker; 134 134 } else 135 return NULL; 135 return NULL; 136 136 }; 137 137 … … 156 156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 157 157 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 159 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 161 161 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 162 * 162 * 163 163 * \param *out output stream for debugging 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 166 166 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule … … 191 191 InBondvector.SubtractVector(&TopOrigin->x); 192 192 bondlength = InBondvector.Norm(); 193 193 194 194 // is greater than typical bond distance? Then we have to correct periodically 195 195 // the problem is not the H being out of the box, but InBondvector have the wrong direction 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 198 198 // *out << Verbose(4) << "InBondvector is: "; 199 199 // InBondvector.Output(out); … … 215 215 // *out << endl; 216 216 } // periodic correction finished 217 217 218 218 InBondvector.Normalize(); 219 219 // get typical bond length and store as scale factor for later … … 222 222 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 223 return false; 224 BondRescale = bondlength; 224 BondRescale = bondlength; 225 225 } else { 226 226 if (!IsAngstroem) … … 273 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 274 274 // *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl; 275 275 276 276 // determine the plane of these two with the *origin 277 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 286 286 Orthovector1.Normalize(); 287 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 288 289 289 // create the two Hydrogens ... 290 290 FirstOtherAtom = new atom(); … … 318 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 319 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 321 SecondOtherAtom->x.Scale(&BondRescale); 322 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 323 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 326 } … … 365 365 // *out << endl; 366 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 368 368 // Orthovector2.Output(out); 369 369 // *out << endl; 370 370 371 371 // create correct coordination for the three atoms 372 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 380 380 factors[0] = d; 381 381 factors[1] = f; 382 factors[2] = 0.; 382 factors[2] = 0.; 383 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 384 factors[1] = -0.5*f; 385 factors[2] = g; 385 factors[2] = g; 386 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 387 factors[2] = -g; 388 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 389 … … 437 437 */ 438 438 bool molecule::AddXYZFile(string filename) 439 { 439 { 440 440 istringstream *input = NULL; 441 441 int NumberOfAtoms = 0; // atom number in xyz read … … 446 446 string line; // currently parsed line 447 447 double x[3]; // atom coordinates 448 448 449 449 xyzfile.open(filename.c_str()); 450 450 if (!xyzfile) … … 454 454 input = new istringstream(line); 455 455 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 457 getline(xyzfile,line,'\n'); // Read comment 458 458 cout << Verbose(1) << "Comment: " << line << endl; 459 459 460 460 if (MDSteps == 0) // no atoms yet present 461 461 MDSteps++; … … 491 491 xyzfile.close(); 492 492 delete(input); 493 return true; 493 return true; 494 494 }; 495 495 … … 503 503 atom *LeftAtom = NULL, *RightAtom = NULL; 504 504 atom *Walker = NULL; 505 505 506 506 // copy all atoms 507 507 Walker = start; … … 510 510 CurrentAtom = copy->AddCopyAtom(Walker); 511 511 } 512 512 513 513 // copy all bonds 514 514 bond *Binder = first; … … 534 534 copy->NoCyclicBonds++; 535 535 NewBond->Type = Binder->Type; 536 } 536 } 537 537 // correct fathers 538 538 Walker = copy->start; … … 551 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 552 } 553 553 554 554 return copy; 555 555 }; … … 576 576 577 577 /** Remove bond from bond chain list. 578 * \todo Function not implemented yet 578 * \todo Function not implemented yet 579 579 * \param *pointer bond pointer 580 580 * \return true - bound found and removed, false - bond not found/removed … … 588 588 589 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 590 * \todo Function not implemented yet 590 * \todo Function not implemented yet 591 591 * \param *BondPartner atom to be removed 592 592 * \return true - bounds found and removed, false - bonds not found/removed … … 621 621 Vector *min = new Vector; 622 622 Vector *max = new Vector; 623 623 624 624 // gather min and max for each axis 625 625 ptr = start->next; // start at first in list … … 667 667 { 668 668 Vector *min = new Vector; 669 669 670 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 671 atom *ptr = start->next; // start at first in list … … 683 683 } 684 684 } 685 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 686 686 // max->Output(out); 687 687 // *out << ", Minimum is "; … … 691 691 max->AddVector(min); 692 692 Translate(min); 693 } 693 } 694 694 delete(min); 695 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 }; 696 }; 697 697 698 698 /** Centers the center of the atoms at (0,0,0). … … 704 704 int Num = 0; 705 705 atom *ptr = start->next; // start at first in list 706 706 707 707 for(int i=NDIM;i--;) // zero center vector 708 708 center->x[i] = 0.; 709 709 710 710 if (ptr != end) { //list not empty? 711 711 while (ptr->next != end) { // continue with second if present 712 712 ptr = ptr->next; 713 713 Num++; 714 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 715 715 } 716 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 717 Translate(center); 718 718 } 719 }; 719 }; 720 720 721 721 /** Returns vector pointing to center of gravity. … … 729 729 Vector tmp; 730 730 double Num = 0; 731 731 732 732 a->Zero(); 733 733 … … 737 737 Num += 1.; 738 738 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 739 a->AddVector(&tmp); 740 740 } 741 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 757 757 Vector tmp; 758 758 double Num = 0; 759 759 760 760 a->Zero(); 761 761 … … 766 766 tmp.CopyVector(&ptr->x); 767 767 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 768 a->AddVector(&tmp); 769 769 } 770 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 789 789 Translate(center); 790 790 } 791 }; 791 }; 792 792 793 793 /** Scales all atoms by \a *factor. … … 803 803 Trajectories[ptr].R.at(j).Scale(factor); 804 804 ptr->x.Scale(factor); 805 } 806 }; 807 808 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 809 809 * \param trans[] translation vector. 810 810 */ … … 818 818 Trajectories[ptr].R.at(j).Translate(trans); 819 819 ptr->x.Translate(trans); 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 824 824 * \param n[] normal vector of mirror plane. 825 825 */ … … 833 833 Trajectories[ptr].R.at(j).Mirror(n); 834 834 ptr->x.Mirror(n); 835 } 835 } 836 836 }; 837 837 … … 847 847 bool flag; 848 848 Vector Testvector, Translationvector; 849 849 850 850 do { 851 851 Center.Zero(); … … 863 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 864 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 866 if ((fabs(tmp)) > BondDistance) { 867 867 flag = false; … … 879 879 cout << Verbose(1) << "vector is: "; 880 880 Testvector.Output((ofstream *)&cout); 881 cout << endl; 881 cout << endl; 882 882 #ifdef ADDHYDROGEN 883 883 // now also change all hydrogens … … 892 892 cout << Verbose(1) << "Hydrogen vector is: "; 893 893 Testvector.Output((ofstream *)&cout); 894 cout << endl; 894 cout << endl; 895 895 } 896 896 } … … 914 914 915 915 CenterGravity(out, CenterOfGravity); 916 917 // reset inertia tensor 916 917 // reset inertia tensor 918 918 for(int i=0;i<NDIM*NDIM;i++) 919 919 InertiaTensor[i] = 0.; 920 920 921 921 // sum up inertia tensor 922 922 while (ptr->next != end) { … … 943 943 } 944 944 *out << endl; 945 945 946 946 // diagonalize to determine principal axis system 947 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 952 952 gsl_eigen_symmv_free(T); 953 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 954 954 955 955 for(int i=0;i<NDIM;i++) { 956 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 957 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 958 958 } 959 959 960 960 // check whether we rotate or not 961 961 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 963 // the eigenvectors specify the transformation matrix 964 964 ptr = start; … … 972 972 973 973 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 974 // reset inertia tensor 975 975 for(int i=0;i<NDIM*NDIM;i++) 976 976 InertiaTensor[i] = 0.; 977 977 978 978 // sum up inertia tensor 979 979 ptr = start; … … 1002 1002 *out << endl; 1003 1003 } 1004 1004 1005 1005 // free everything 1006 1006 delete(CenterOfGravity); … … 1031 1031 1032 1032 CountElements(); // make sure ElementsInMolecule is up to date 1033 1033 1034 1034 // check file 1035 1035 if (input == NULL) { … … 1087 1087 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass; 1088 1088 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 1090 // for (int d=0;d<NDIM;d++) 1091 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step … … 1121 1121 MDSteps++; 1122 1122 1123 1123 1124 1124 // exit 1125 1125 return true; 1126 1126 }; 1127 1127 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1129 1129 * \param n[] alignment vector. 1130 1130 */ … … 1145 1145 ptr = ptr->next; 1146 1146 tmp = ptr->x.x[0]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1148 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1149 1149 for (int j=0;j<MDSteps;j++) { 1150 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1152 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1153 1153 } 1154 } 1154 } 1155 1155 // rotate n vector 1156 1156 tmp = n->x[0]; … … 1160 1160 n->Output((ofstream *)&cout); 1161 1161 cout << endl; 1162 1162 1163 1163 // rotate on z-y plane 1164 1164 ptr = start; … … 1168 1168 ptr = ptr->next; 1169 1169 tmp = ptr->x.x[1]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1171 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1172 1172 for (int j=0;j<MDSteps;j++) { 1173 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1175 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 1176 } 1177 } 1177 } 1178 1178 // rotate n vector (for consistency check) 1179 1179 tmp = n->x[1]; 1180 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1181 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1182 1182 1183 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1184 1184 n->Output((ofstream *)&cout); … … 1191 1191 * \return true - succeeded, false - atom not found in list 1192 1192 */ 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1195 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1196 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1197 1197 else 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1199 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1200 1200 ElementCount--; … … 1206 1206 * \return true - succeeded, false - atom not found in list 1207 1207 */ 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1211 1211 }; 1212 1212 … … 1222 1222 } else { 1223 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1224 return NULL; 1224 return NULL; 1225 1225 } 1226 1226 }; … … 1271 1271 struct lsq_params *par = (struct lsq_params *)params; 1272 1272 atom *ptr = par->mol->start; 1273 1273 1274 1274 // initialize vectors 1275 1275 a.x[0] = gsl_vector_get(x,0); … … 1301 1301 { 1302 1302 int np = 6; 1303 1303 1304 1304 const gsl_multimin_fminimizer_type *T = 1305 1305 gsl_multimin_fminimizer_nmsimplex; … … 1307 1307 gsl_vector *ss; 1308 1308 gsl_multimin_function minex_func; 1309 1309 1310 1310 size_t iter = 0, i; 1311 1311 int status; 1312 1312 double size; 1313 1313 1314 1314 /* Initial vertex size vector */ 1315 1315 ss = gsl_vector_alloc (np); 1316 1316 1317 1317 /* Set all step sizes to 1 */ 1318 1318 gsl_vector_set_all (ss, 1.0); 1319 1319 1320 1320 /* Starting point */ 1321 1321 par->x = gsl_vector_alloc (np); 1322 1322 par->mol = this; 1323 1323 1324 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1325 1325 gsl_vector_set (par->x, 1, 0.0); … … 1328 1328 gsl_vector_set (par->x, 4, 0.0); 1329 1329 gsl_vector_set (par->x, 5, 1.0); 1330 1330 1331 1331 /* Initialize method and iterate */ 1332 1332 minex_func.f = &LeastSquareDistance; 1333 1333 minex_func.n = np; 1334 1334 minex_func.params = (void *)par; 1335 1335 1336 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1337 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1338 1338 1339 1339 do 1340 1340 { 1341 1341 iter++; 1342 1342 status = gsl_multimin_fminimizer_iterate(s); 1343 1343 1344 1344 if (status) 1345 1345 break; 1346 1346 1347 1347 size = gsl_multimin_fminimizer_size (s); 1348 1348 status = gsl_multimin_test_size (size, 1e-2); 1349 1349 1350 1350 if (status == GSL_SUCCESS) 1351 1351 { 1352 1352 printf ("converged to minimum at\n"); 1353 1353 } 1354 1354 1355 1355 printf ("%5d ", (int)iter); 1356 1356 for (i = 0; i < (size_t)np; i++) … … 1361 1361 } 1362 1362 while (status == GSL_CONTINUE && iter < 100); 1363 1363 1364 1364 for (i=0;i<(size_t)np;i++) 1365 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 1378 1378 int ElementNo, AtomNo; 1379 1379 CountElements(); 1380 1380 1381 1381 if (out == NULL) { 1382 1382 return false; … … 1413 1413 int ElementNo, AtomNo; 1414 1414 CountElements(); 1415 1415 1416 1416 if (out == NULL) { 1417 1417 return false; … … 1460 1460 atom *Walker = start; 1461 1461 while (Walker->next != end) { 1462 Walker = Walker->next; 1462 Walker = Walker->next; 1463 1463 #ifdef ADDHYDROGEN 1464 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 1491 1491 int No = 0; 1492 1492 time_t now; 1493 1493 1494 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1495 1495 walker = start; … … 1518 1518 { 1519 1519 atom *walker = NULL; 1520 int No = 0;1520 int AtomNo = 0, ElementNo; 1521 1521 time_t now; 1522 1522 element *runner = NULL; 1523 1523 1524 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1524 1525 walker = start; 1525 1526 while (walker->next != end) { // go through every atom and count 1526 1527 walker = walker->next; 1527 No++;1528 AtomNo++; 1528 1529 } 1529 1530 if (out != NULL) { 1530 *out << No << "\n\tCreated by molecuilder on " << ctime(&now); 1531 walker = start; 1532 while (walker->next != end) { // go through every atom of this element 1533 walker = walker->next; 1534 walker->OutputXYZLine(out); 1531 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1532 ElementNo = 0; 1533 runner = elemente->start; 1534 while (runner->next != elemente->end) { // go through every element 1535 runner = runner->next; 1536 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1537 ElementNo++; 1538 walker = start; 1539 while (walker->next != end) { // go through every atom of this element 1540 walker = walker->next; 1541 if (walker->type == runner) { // if this atom fits to element 1542 walker->OutputXYZLine(out); 1543 } 1544 } 1545 } 1535 1546 } 1536 1547 return true; … … 1563 1574 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1564 1575 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1565 NoNonHydrogen++; 1576 NoNonHydrogen++; 1566 1577 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1567 1578 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 1571 1582 } 1572 1583 } else 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1584 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1574 1585 } 1575 1586 }; … … 1583 1594 ElementsInMolecule[i] = 0; 1584 1595 ElementCount = 0; 1585 1596 1586 1597 atom *walker = start; 1587 1598 while (walker->next != end) { … … 1619 1630 Binder = Binder->next; 1620 1631 if (Binder->Cyclic) 1621 No++; 1632 No++; 1622 1633 } 1623 1634 delete(BackEdgeStack); … … 1677 1688 1678 1689 /** Creates an adjacency list of the molecule. 1690 * We obtain an outside file with the indices of atoms which are bondmembers. 1691 */ 1692 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input) 1693 { 1694 1695 // 1 We will parse bonds out of the dbond file created by tremolo. 1696 int atom1, atom2, temp; 1697 atom *Walker, *OtherWalker; 1698 1699 if (!input) 1700 { 1701 cout << Verbose(1) << "Opening silica failed \n"; 1702 }; 1703 1704 *input >> ws >> atom1; 1705 *input >> ws >> atom2; 1706 cout << Verbose(1) << "Scanning file\n"; 1707 while (!input->eof()) // Check whether we read everything already 1708 { 1709 *input >> ws >> atom1; 1710 *input >> ws >> atom2; 1711 if(atom2<atom1) //Sort indices of atoms in order 1712 { 1713 temp=atom1; 1714 atom1=atom2; 1715 atom2=temp; 1716 }; 1717 1718 Walker=start; 1719 while(Walker-> nr != atom1) // Find atom corresponding to first index 1720 { 1721 Walker = Walker->next; 1722 }; 1723 OtherWalker = Walker->next; 1724 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1725 { 1726 OtherWalker= OtherWalker->next; 1727 }; 1728 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1729 1730 } 1731 1732 CreateListOfBondsPerAtom(out); 1733 1734 }; 1735 1736 1737 /** Creates an adjacency list of the molecule. 1679 1738 * Generally, we use the CSD approach to bond recognition, that is the the distance 1680 1739 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 1681 * a threshold t = 0.4 Angstroem. 1740 * a threshold t = 0.4 Angstroem. 1682 1741 * To make it O(N log N) the function uses the linked-cell technique as follows: 1683 1742 * The procedure is step-wise: … … 1696 1755 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 1697 1756 { 1757 1698 1758 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1699 1759 int No, NoBonds, CandidateBondNo; … … 1704 1764 Vector x; 1705 1765 int FalseBondDegree = 0; 1706 1766 1707 1767 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1708 1768 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 1711 1771 cleanup(first,last); 1712 1772 } 1713 1773 1714 1774 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1715 1775 CountAtoms(out); … … 1730 1790 for (int i=NumberCells;i--;) 1731 1791 CellList[i] = NULL; 1732 1792 1733 1793 // 2b. put all atoms into its corresponding list 1734 1794 Walker = start; … … 1751 1811 if (CellList[index] == NULL) // allocate molecule if not done 1752 1812 CellList[index] = new molecule(elemente); 1753 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1754 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 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; 1755 1815 } 1756 1816 //for (int i=0;i<NumberCells;i++) 1757 1817 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1758 1818 1819 1759 1820 // 3a. go through every cell 1760 1821 for (N[0]=divisor[0];N[0]--;) … … 1769 1830 Walker = Walker->next; 1770 1831 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1771 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1832 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1772 1833 for (n[0]=-1;n[0]<=1;n[0]++) 1773 1834 for (n[1]=-1;n[1]<=1;n[1]++) … … 1801 1862 } 1802 1863 } 1864 1865 1866 1803 1867 // 4. free the cell again 1804 1868 for (int i=NumberCells;i--;) … … 1807 1871 } 1808 1872 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1809 1873 1810 1874 // create the adjacency list per atom 1811 1875 CreateListOfBondsPerAtom(out); 1812 1876 1813 1877 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1814 1878 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 1859 1923 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1860 1924 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1861 1925 1862 1926 // output bonds for debugging (if bond chain list was correctly installed) 1863 1927 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 1869 1933 *out << endl; 1870 1934 } else 1871 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1935 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1872 1936 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1873 1937 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1874 }; 1938 1939 }; 1940 1941 1875 1942 1876 1943 /** Performs a Depth-First search on this molecule. … … 1893 1960 bond *Binder = NULL; 1894 1961 bool BackStepping = false; 1895 1962 1896 1963 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1897 1964 1898 1965 ResetAllBondsToUnused(); 1899 1966 ResetAllAtomNumbers(); … … 1908 1975 LeafWalker->Leaf = new molecule(elemente); 1909 1976 LeafWalker->Leaf->AddCopyAtom(Root); 1910 1977 1911 1978 OldGraphNr = CurrentGraphNr; 1912 1979 Walker = Root; … … 1919 1986 AtomStack->Push(Walker); 1920 1987 CurrentGraphNr++; 1921 } 1988 } 1922 1989 do { // (3) if Walker has no unused egdes, go to (5) 1923 1990 BackStepping = false; // reset backstepping flag for (8) … … 1953 2020 Binder = NULL; 1954 2021 } while (1); // (2) 1955 2022 1956 2023 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished! 1957 2024 if ((Walker == Root) && (Binder == NULL)) 1958 2025 break; 1959 1960 // (5) if Ancestor of Walker is ... 2026 2027 // (5) if Ancestor of Walker is ... 1961 2028 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 1962 2029 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2001 2068 } while (OtherAtom != Walker); 2002 2069 ComponentNumber++; 2003 2070 2004 2071 // (11) Root is separation vertex, set Walker to Root and go to (4) 2005 2072 Walker = Root; … … 2014 2081 2015 2082 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2016 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2083 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2017 2084 LeafWalker->Leaf->Output(out); 2018 2085 *out << endl; … … 2022 2089 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2023 2090 if (Root->GraphNr != -1) // if already discovered, step on 2024 Root = Root->next; 2091 Root = Root->next; 2025 2092 } 2026 2093 } … … 2044 2111 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2045 2112 } 2046 2113 2047 2114 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2048 2115 Binder = first; … … 2055 2122 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2056 2123 OutputComponentNumber(out, Binder->rightatom); 2057 *out << ">." << endl; 2124 *out << ">." << endl; 2058 2125 if (Binder->Cyclic) // cyclic ?? 2059 2126 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2070 2137 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2071 2138 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2072 * as cyclic and print out the cycles. 2139 * as cyclic and print out the cycles. 2073 2140 * \param *out output stream for debugging 2074 2141 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph! … … 2081 2148 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2082 2149 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2083 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2150 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2084 2151 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2085 2152 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2093 2160 ColorList[i] = white; 2094 2161 } 2095 2162 2096 2163 *out << Verbose(1) << "Back edge list - "; 2097 2164 BackEdgeStack->Output(out); 2098 2165 2099 2166 *out << Verbose(1) << "Analysing cycles ... " << endl; 2100 2167 NumCycles = 0; … … 2102 2169 BackEdge = BackEdgeStack->PopFirst(); 2103 2170 // this is the target 2104 Root = BackEdge->leftatom; 2171 Root = BackEdge->leftatom; 2105 2172 // this is the source point 2106 Walker = BackEdge->rightatom; 2173 Walker = BackEdge->rightatom; 2107 2174 ShortestPathList[Walker->nr] = 0; 2108 2175 BFSStack->ClearStack(); // start with empty BFS stack … … 2118 2185 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2119 2186 OtherAtom = Binder->GetOtherAtom(Walker); 2120 #ifdef ADDHYDROGEN 2187 #ifdef ADDHYDROGEN 2121 2188 if (OtherAtom->type->Z != 1) { 2122 2189 #endif … … 2127 2194 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2128 2195 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2129 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 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; 2130 2197 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2131 2198 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2137 2204 if (OtherAtom == Root) 2138 2205 break; 2139 #ifdef ADDHYDROGEN 2206 #ifdef ADDHYDROGEN 2140 2207 } else { 2141 2208 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2175 2242 } 2176 2243 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2177 2244 2178 2245 if (OtherAtom == Root) { 2179 2246 // now climb back the predecessor list and thus find the cycle members … … 2203 2270 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2204 2271 } 2205 2272 2206 2273 // now clean the lists 2207 2274 while (!TouchedStack->IsEmpty()){ … … 2213 2280 } 2214 2281 if (MinRingSize != -1) { 2215 // go over all atoms 2282 // go over all atoms 2216 2283 Root = start; 2217 2284 while(Root->next != end) { 2218 2285 Root = Root->next; 2219 2286 2220 2287 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2221 2288 Walker = Root; … … 2254 2321 } 2255 2322 ColorList[Walker->nr] = black; 2256 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2323 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2257 2324 } 2258 2325 2259 2326 // now clean the lists 2260 2327 while (!TouchedStack->IsEmpty()){ … … 2305 2372 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2306 2373 { 2307 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2374 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2308 2375 *out << vertex->ComponentNr[i] << " "; 2309 2376 }; … … 2383 2450 { 2384 2451 int c = 0; 2385 int FragmentCount; 2452 int FragmentCount; 2386 2453 // get maximum bond degree 2387 2454 atom *Walker = start; … … 2393 2460 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2394 2461 return FragmentCount; 2395 }; 2462 }; 2396 2463 2397 2464 /** Scans a single line for number and puts them into \a KeySet. 2398 2465 * \param *out output stream for debugging 2399 2466 * \param *buffer buffer to scan 2400 * \param &CurrentSet filled KeySet on return 2467 * \param &CurrentSet filled KeySet on return 2401 2468 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 2402 2469 */ … … 2406 2473 int AtomNr; 2407 2474 int status = 0; 2408 2475 2409 2476 line.str(buffer); 2410 2477 while (!line.eof()) { … … 2442 2509 double TEFactor; 2443 2510 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2444 2511 2445 2512 if (FragmentList == NULL) { // check list pointer 2446 2513 FragmentList = new Graph; 2447 2514 } 2448 2515 2449 2516 // 1st pass: open file and read 2450 2517 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 2475 2542 status = false; 2476 2543 } 2477 2544 2478 2545 // 2nd pass: open TEFactors file and read 2479 2546 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 2487 2554 InputFile >> TEFactor; 2488 2555 (*runner).second.second = TEFactor; 2489 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2556 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2490 2557 } else { 2491 2558 status = false; … … 2528 2595 if(output != NULL) { 2529 2596 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2530 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2597 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2531 2598 if (sprinter != (*runner).first.begin()) 2532 2599 output << "\t"; … … 2594 2661 status = false; 2595 2662 } 2596 2663 2597 2664 return status; 2598 2665 }; … … 2603 2670 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 2604 2671 * \return true - structure is equal, false - not equivalence 2605 */ 2672 */ 2606 2673 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2607 2674 { … … 2610 2677 bool status = true; 2611 2678 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2612 2679 2613 2680 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2614 2681 File.open(filename.str().c_str(), ios::out); … … 2669 2736 *out << endl; 2670 2737 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2671 2738 2672 2739 return status; 2673 2740 }; … … 2691 2758 for(int i=AtomCount;i--;) 2692 2759 AtomMask[i] = false; 2693 2760 2694 2761 if (Order < 0) { // adaptive increase of BondOrder per site 2695 2762 if (AtomMask[AtomCount] == true) // break after one step … … 2731 2798 line >> ws >> Value; // skip time entry 2732 2799 line >> ws >> Value; 2733 No -= 1; // indices start at 1 in file, not 0 2800 No -= 1; // indices start at 1 in file, not 0 2734 2801 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2735 2802 … … 2740 2807 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 2741 2808 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2742 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2809 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2743 2810 if (!InsertedElement.second) { // this root is already present 2744 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2745 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 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) 2746 2813 { // if value is smaller, update value and order 2747 2814 (*PresentItem).second.first = fabs(Value); … … 2781 2848 Walker = FindAtom(No); 2782 2849 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2783 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2850 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2784 2851 AtomMask[No] = true; 2785 2852 status = true; 2786 2853 //} else 2787 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 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; 2788 2855 } 2789 2856 // close and done … … 2819 2886 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2820 2887 status = true; 2821 2888 2822 2889 if (!status) { 2823 2890 if (Order == 0) … … 2827 2894 } 2828 2895 } 2829 2896 2830 2897 // print atom mask for debugging 2831 2898 *out << " "; … … 2836 2903 *out << (AtomMask[i] ? "t" : "f"); 2837 2904 *out << endl; 2838 2905 2839 2906 return status; 2840 2907 }; … … 2850 2917 int AtomNo = 0; 2851 2918 atom *Walker = NULL; 2852 2919 2853 2920 if (SortIndex != NULL) { 2854 2921 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 2908 2975 atom **ListOfAtoms = NULL; 2909 2976 atom ***ListOfLocalAtoms = NULL; 2910 bool *AtomMask = NULL; 2911 2977 bool *AtomMask = NULL; 2978 2912 2979 *out << endl; 2913 2980 #ifdef ADDHYDROGEN … … 2918 2985 2919 2986 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 2920 2987 2921 2988 // ===== 1. Check whether bond structure is same as stored in files ==== 2922 2989 2923 2990 // fill the adjacency list 2924 2991 CreateListOfBondsPerAtom(out); … … 2926 2993 // create lookup table for Atom::nr 2927 2994 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 2928 2995 2929 2996 // === compare it with adjacency file === 2930 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2997 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2931 2998 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2932 2999 … … 2957 3024 delete(LocalBackEdgeStack); 2958 3025 } 2959 3026 2960 3027 // ===== 3. if structure still valid, parse key set file and others ===== 2961 3028 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 2963 3030 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 2964 3031 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 2965 2966 // =================================== Begin of FRAGMENTATION =============================== 2967 // ===== 6a. assign each keyset to its respective subgraph ===== 3032 3033 // =================================== Begin of FRAGMENTATION =============================== 3034 // ===== 6a. assign each keyset to its respective subgraph ===== 2968 3035 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 2969 3036 … … 2976 3043 FragmentationToDo = FragmentationToDo || CheckOrder; 2977 3044 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 2978 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3045 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 2979 3046 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 2980 3047 … … 3000 3067 delete(ParsedFragmentList); 3001 3068 delete[](MinimumRingSize); 3002 3069 3003 3070 3004 3071 // ==================================== End of FRAGMENTATION ============================================ … … 3006 3073 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3007 3074 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3008 3075 3009 3076 // free subgraph memory again 3010 3077 FragmentCounter = 0; … … 3031 3098 } 3032 3099 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3033 3100 3034 3101 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3035 3102 if (BondFragments->NumberOfMolecules != 0) { 3036 3103 // create the SortIndex from BFS labels to order in the config file 3037 3104 CreateMappingLabelsToConfigSequence(out, SortIndex); 3038 3105 3039 3106 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3040 3107 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) … … 3042 3109 else 3043 3110 *out << Verbose(1) << "Some config writing failed." << endl; 3044 3111 3045 3112 // store force index reference file 3046 3113 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3047 3048 // store keysets file 3114 3115 // store keysets file 3049 3116 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3050 3051 // store Adjacency file 3117 3118 // store Adjacency file 3052 3119 StoreAdjacencyToFile(out, configuration->configpath); 3053 3120 3054 3121 // store Hydrogen saturation correction file 3055 3122 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3056 3123 3057 3124 // store adaptive orders into file 3058 3125 StoreOrderAtSiteFile(out, configuration->configpath); 3059 3126 3060 3127 // restore orbital and Stop values 3061 3128 CalculateOrbitals(*configuration); 3062 3129 3063 3130 // free memory for bond part 3064 3131 *out << Verbose(1) << "Freeing bond memory" << endl; 3065 3132 delete(FragmentList); // remove bond molecule from memory 3066 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3133 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3067 3134 } else 3068 3135 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3069 //} else 3136 //} else 3070 3137 // *out << Verbose(1) << "No fragments to store." << endl; 3071 3138 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3093 3160 atom *Walker = NULL, *OtherAtom = NULL; 3094 3161 ReferenceStack->Push(Binder); 3095 3162 3096 3163 do { // go through all bonds and push local ones 3097 3164 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3098 if (Walker != NULL) // if this Walker exists in the subgraph ... 3165 if (Walker != NULL) // if this Walker exists in the subgraph ... 3099 3166 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3100 3167 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); … … 3109 3176 ReferenceStack->Push(Binder); 3110 3177 } while (FirstBond != Binder); 3111 3178 3112 3179 return status; 3113 3180 }; … … 3185 3252 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3186 3253 Walker->MaxOrder = MaxArray[Walker->nr]; 3187 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3254 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3188 3255 } 3189 3256 file.close(); … … 3196 3263 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3197 3264 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3198 3265 3199 3266 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3200 3267 return status; … … 3254 3321 Walker = start; 3255 3322 while (Walker->next != end) { 3256 Walker = Walker->next; 3323 Walker = Walker->next; 3257 3324 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3258 3325 TotalDegree = 0; … … 3262 3329 } 3263 3330 *out << " -- TotalDegree: " << TotalDegree << endl; 3264 } 3331 } 3265 3332 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3266 3333 }; … … 3268 3335 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3269 3336 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3270 * white and putting into queue. 3337 * white and putting into queue. 3271 3338 * \param *out output stream for debugging 3272 3339 * \param *Mol Molecule class to add atoms to … … 3277 3344 * \param BondOrder maximum distance for vertices to add 3278 3345 * \param IsAngstroem lengths are in angstroem or bohrradii 3279 */ 3346 */ 3280 3347 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3281 3348 { … … 3303 3370 } 3304 3371 ShortestPathList[Root->nr] = 0; 3305 3372 3306 3373 // and go on ... Queue always contains all lightgray vertices 3307 3374 while (!AtomStack->IsEmpty()) { … … 3311 3378 // followed by n+1 till top of stack. 3312 3379 Walker = AtomStack->PopFirst(); // pop oldest added 3313 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3380 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3314 3381 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3315 3382 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3318 3385 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3319 3386 if (ColorList[OtherAtom->nr] == white) { 3320 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 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) 3321 3388 ColorList[OtherAtom->nr] = lightgray; 3322 3389 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3323 3390 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3324 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 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; 3325 3392 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3326 3393 *out << Verbose(3); … … 3370 3437 // This has to be a cyclic bond, check whether it's present ... 3371 3438 if (AddedBondList[Binder->nr] == NULL) { 3372 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3439 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3373 3440 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3374 3441 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3385 3452 } 3386 3453 ColorList[Walker->nr] = black; 3387 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3454 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3388 3455 } 3389 3456 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 3409 3476 3410 3477 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3411 3478 3412 3479 // reset parent list 3413 3480 *out << Verbose(3) << "Resetting ParentList." << endl; 3414 3481 for (int i=Father->AtomCount;i--;) 3415 3482 ParentList[i] = NULL; 3416 3483 3417 3484 // fill parent list with sons 3418 3485 *out << Verbose(3) << "Filling Parent List." << endl; … … 3455 3522 * \param *&Leaf KeySet to look through 3456 3523 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 3457 * \param index of the atom suggested for removal 3524 * \param index of the atom suggested for removal 3458 3525 */ 3459 3526 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 3461 3528 atom *Runner = NULL; 3462 3529 int SP, Removal; 3463 3530 3464 3531 *out << Verbose(2) << "Looking for removal candidate." << endl; 3465 3532 SP = -1; //0; // not -1, so that Root is never removed … … 3479 3546 /** Stores a fragment from \a KeySet into \a molecule. 3480 3547 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 3481 * molecule and adds missing hydrogen where bonds were cut. 3548 * molecule and adds missing hydrogen where bonds were cut. 3482 3549 * \param *out output stream for debugging messages 3483 * \param &Leaflet pointer to KeySet structure 3550 * \param &Leaflet pointer to KeySet structure 3484 3551 * \param IsAngstroem whether we have Ansgtroem or bohrradius 3485 3552 * \return pointer to constructed molecule … … 3492 3559 bool LonelyFlag = false; 3493 3560 int size; 3494 3561 3495 3562 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3496 3563 3497 3564 Leaf->BondDistance = BondDistance; 3498 3565 for(int i=NDIM*2;i--;) 3499 Leaf->cell_size[i] = cell_size[i]; 3566 Leaf->cell_size[i] = cell_size[i]; 3500 3567 3501 3568 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 3510 3577 size++; 3511 3578 } 3512 3579 3513 3580 // create the bonds between all: Make it an induced subgraph and add hydrogen 3514 3581 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 3520 3587 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3521 3588 // create all bonds 3522 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3589 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3523 3590 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3524 3591 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3525 3592 if (SonList[OtherFather->nr] != NULL) { 3526 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3593 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3527 3594 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3528 3595 // *out << Verbose(3) << "Adding Bond: "; 3529 // *out << 3596 // *out << 3530 3597 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3531 3598 // *out << "." << endl; 3532 3599 //NumBonds[Runner->nr]++; 3533 } else { 3600 } else { 3534 3601 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3535 3602 } 3536 3603 LonelyFlag = false; 3537 3604 } else { 3538 // *out << ", who has no son in this fragment molecule." << endl; 3605 // *out << ", who has no son in this fragment molecule." << endl; 3539 3606 #ifdef ADDHYDROGEN 3540 3607 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; … … 3554 3621 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3555 3622 Runner = Runner->next; 3556 #endif 3623 #endif 3557 3624 } 3558 3625 Leaf->CreateListOfBondsPerAtom(out); … … 3587 3654 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 3588 3655 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack! 3589 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3656 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3590 3657 MoleculeListClass *FragmentList = NULL; 3591 3658 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 3637 3704 // clear snake stack 3638 3705 SnakeStack->ClearStack(); 3639 //SnakeStack->TestImplementation(out, start->next); 3706 //SnakeStack->TestImplementation(out, start->next); 3640 3707 3641 3708 ///// INNER LOOP //////////// … … 3658 3725 } 3659 3726 if (ShortestPathList[Walker->nr] == -1) { 3660 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3727 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3661 3728 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 3662 3729 } … … 3696 3763 OtherAtom = Binder->GetOtherAtom(Walker); 3697 3764 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 3698 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3765 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3699 3766 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 3700 3767 } else { // otherwise check its colour and element 3701 3768 if ( 3702 3769 #ifdef ADDHYDROGEN 3703 (OtherAtom->type->Z != 1) && 3770 (OtherAtom->type->Z != 1) && 3704 3771 #endif 3705 3772 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 3711 3778 //} else { 3712 3779 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3713 //} 3780 //} 3714 3781 Walker = OtherAtom; 3715 3782 break; 3716 3783 } else { 3717 if (OtherAtom->type->Z == 1) 3784 if (OtherAtom->type->Z == 1) 3718 3785 *out << "Links to a hydrogen atom." << endl; 3719 else 3786 else 3720 3787 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 3721 3788 } … … 3727 3794 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 3728 3795 } 3729 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3796 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3730 3797 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 3731 3798 ColorVertexList[Walker->nr] = black; … … 3734 3801 } 3735 3802 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 3736 *out << Verbose(2) << "Inner Looping is finished." << endl; 3803 *out << Verbose(2) << "Inner Looping is finished." << endl; 3737 3804 3738 3805 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 3750 3817 } 3751 3818 } 3752 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3819 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3753 3820 3754 3821 // copy together 3755 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3822 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3756 3823 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 3757 3824 RunningIndex = 0; … … 3824 3891 3825 3892 NumCombinations = 1 << SetDimension; 3826 3893 3827 3894 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3828 3895 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3829 3896 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3830 3897 3831 3898 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3832 3899 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " << NumCombinations-1 << " combination(s)." << endl; 3833 3900 3834 // initialised touched list (stores added atoms on this level) 3901 // initialised touched list (stores added atoms on this level) 3835 3902 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3836 3903 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3837 3904 TouchedList[TouchedIndex] = -1; 3838 3905 TouchedIndex = 0; 3839 3906 3840 3907 // create every possible combination of the endpieces 3841 3908 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 3845 3912 for (int j=SetDimension;j--;) 3846 3913 bits += (i & (1 << j)) >> j; 3847 3914 3848 3915 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3849 3916 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 3853 3920 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3854 3921 if (bit) { // if bit is set, we add this bond partner 3855 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3922 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3856 3923 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3857 3924 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3858 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3925 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3859 3926 if (TestKeySetInsert.second) { 3860 3927 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 3869 3936 } 3870 3937 } 3871 3872 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3938 3939 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3873 3940 if (SpaceLeft > 0) { 3874 3941 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 3898 3965 } 3899 3966 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3900 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3967 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3901 3968 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3902 3969 } … … 3907 3974 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3908 3975 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3909 *out << (*runner) << " "; 3976 *out << (*runner) << " "; 3910 3977 *out << endl; 3911 3978 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 3915 3982 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3916 3983 } 3917 3984 3918 3985 // --3-- remove all added items in this level from snake stack 3919 3986 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 3926 3993 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3927 3994 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3928 *out << (*runner) << " "; 3995 *out << (*runner) << " "; 3929 3996 *out << endl; 3930 3997 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 3933 4000 } 3934 4001 } 3935 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 4002 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3936 4003 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3937 4004 }; … … 3942 4009 * \return true - connected, false - disconnected 3943 4010 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 3944 */ 4011 */ 3945 4012 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3946 4013 { … … 3948 4015 bool BondStatus = false; 3949 4016 int size; 3950 4017 3951 4018 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3952 4019 *out << Verbose(2) << "Disconnected atom: "; 3953 4020 3954 4021 // count number of atoms in graph 3955 4022 size = 0; … … 3997 4064 * \param *out output stream for debugging 3998 4065 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 3999 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4066 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4000 4067 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4001 4068 * \return number of inserted fragments 4002 4069 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4003 4070 */ 4004 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4071 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4005 4072 { 4006 4073 int SP, AtomKeyNr; … … 4023 4090 FragmentSearch.BondsPerSPCount[i] = 0; 4024 4091 FragmentSearch.BondsPerSPCount[0] = 1; 4025 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4092 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4026 4093 add(Binder, FragmentSearch.BondsPerSPList[1]); 4027 4094 4028 4095 // do a BFS search to fill the SP lists and label the found vertices 4029 4096 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4030 4097 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4031 4098 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4032 // (EdgeinSPLevel) of this tree ... 4099 // (EdgeinSPLevel) of this tree ... 4033 4100 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4034 4101 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4083 4150 } 4084 4151 } 4085 4152 4086 4153 // outputting all list for debugging 4087 4154 *out << Verbose(0) << "Printing all found lists." << endl; … … 4092 4159 Binder = Binder->next; 4093 4160 *out << Verbose(2) << *Binder << endl; 4094 } 4095 } 4096 4161 } 4162 } 4163 4097 4164 // creating fragments with the found edge sets (may be done in reverse order, faster) 4098 4165 SP = -1; // the Root <-> Root edge must be subtracted! … … 4101 4168 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4102 4169 Binder = Binder->next; 4103 SP ++; 4170 SP ++; 4104 4171 } 4105 4172 } … … 4108 4175 // start with root (push on fragment stack) 4109 4176 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4110 FragmentSearch.FragmentSet->clear(); 4177 FragmentSearch.FragmentSet->clear(); 4111 4178 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4112 4179 // prepare the subset and call the generator 4113 4180 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4114 4181 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4115 4182 4116 4183 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4117 4184 4118 4185 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4119 4186 } else { … … 4124 4191 // remove root from stack 4125 4192 *out << Verbose(0) << "Removing root again from stack." << endl; 4126 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4193 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4127 4194 4128 4195 // free'ing the bonds lists … … 4143 4210 } 4144 4211 4145 // return list 4212 // return list 4146 4213 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4147 4214 return (FragmentSearch.FragmentCounter - Counter); … … 4174 4241 // remove bonds that are beyond bonddistance 4175 4242 for(int i=NDIM;i--;) 4176 Translationvector.x[i] = 0.; 4243 Translationvector.x[i] = 0.; 4177 4244 // scan all bonds 4178 4245 Binder = first; … … 4221 4288 } 4222 4289 } 4223 // re-add bond 4290 // re-add bond 4224 4291 link(Binder, OtherBinder); 4225 4292 } else { … … 4275 4342 IteratorB++; 4276 4343 } // end of while loop 4277 }// end of check in case of equal sizes 4344 }// end of check in case of equal sizes 4278 4345 } 4279 4346 return false; // if we reach this point, they are equal … … 4319 4386 * \param graph1 first (dest) graph 4320 4387 * \param graph2 second (source) graph 4321 * \param *counter keyset counter that gets increased 4388 * \param *counter keyset counter that gets increased 4322 4389 */ 4323 4390 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 4364 4431 int RootKeyNr, RootNr; 4365 4432 struct UniqueFragments FragmentSearch; 4366 4433 4367 4434 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4368 4435 … … 4387 4454 Walker = Walker->next; 4388 4455 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4389 } 4456 } 4390 4457 4391 4458 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as … … 4401 4468 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4402 4469 // *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 4403 //} else 4470 //} else 4404 4471 { 4405 4472 // increase adaptive order by one 4406 4473 Walker->GetTrueFather()->AdaptiveOrder++; 4407 4474 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4408 4475 4409 4476 // initialise Order-dependent entries of UniqueFragments structure 4410 4477 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 4413 4480 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4414 4481 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4415 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4482 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4416 4483 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4417 4484 FragmentSearch.BondsPerSPCount[i] = 0; 4418 } 4419 4485 } 4486 4420 4487 // allocate memory for all lower level orders in this 1D-array of ptrs 4421 4488 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 4423 4490 for (int i=0;i<NumLevels;i++) 4424 4491 FragmentLowerOrdersList[RootNr][i] = NULL; 4425 4492 4426 4493 // create top order where nothing is reduced 4427 4494 *out << Verbose(0) << "==============================================================================================================" << endl; 4428 4495 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4429 4496 4430 4497 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4431 4498 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 4440 4507 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4441 4508 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4442 4509 4443 4510 // if ((NumLevels >> 1) > 0) { 4444 4511 // // create lower order fragments … … 4447 4514 // for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again) 4448 4515 // // step down to next order at (virtual) boundary of powers of 2 in array 4449 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4516 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4450 4517 // Order--; 4451 4518 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 4454 4521 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4455 4522 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4456 // 4523 // 4457 4524 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4458 4525 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 4485 4552 RootStack.push_back(RootKeyNr); // put back on stack 4486 4553 RootNr++; 4487 4554 4488 4555 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4489 4556 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 4491 4558 delete(FragmentSearch.BondsPerSPList[2*i]); 4492 4559 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4493 } 4560 } 4494 4561 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4495 4562 } … … 4502 4569 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4503 4570 delete(FragmentSearch.FragmentSet); 4504 4505 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4571 4572 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4506 4573 // 5433222211111111 4507 4574 // 43221111 … … 4523 4590 RootKeyNr = RootStack.front(); 4524 4591 RootStack.pop_front(); 4525 Walker = FindAtom(RootKeyNr); 4592 Walker = FindAtom(RootKeyNr); 4526 4593 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4527 4594 for(int i=0;i<NumLevels;i++) { … … 4536 4603 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4537 4604 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4538 4605 4539 4606 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4540 4607 }; … … 4570 4637 atom *Walker = NULL; 4571 4638 bool result = true; // status of comparison 4572 4573 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4639 4640 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4574 4641 /// first count both their atoms and elements and update lists thereby ... 4575 4642 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 4618 4685 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 4619 4686 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4620 result = false; 4621 } 4622 } 4623 4687 result = false; 4688 } 4689 } 4690 4624 4691 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4625 4692 if (result) { … … 4637 4704 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 4638 4705 } 4639 4706 4640 4707 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4641 4708 *out << Verbose(5) << "Sorting distances" << endl; … … 4648 4715 for(int i=AtomCount;i--;) 4649 4716 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4650 4717 4651 4718 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4652 4719 *out << Verbose(4) << "Comparing distances" << endl; … … 4659 4726 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4660 4727 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4661 4728 4662 4729 /// free memory 4663 4730 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 4667 4734 result = false; 4668 4735 } 4669 } 4736 } 4670 4737 /// return pointer to map if all distances were below \a threshold 4671 4738 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 4676 4743 *out << Verbose(3) << "Result: Not equal." << endl; 4677 4744 return NULL; 4678 } 4745 } 4679 4746 }; 4680 4747 … … 4731 4798 * \param *output output stream of temperature file 4732 4799 * \return file written (true), failure on writing file (false) 4733 */ 4800 */ 4734 4801 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4735 4802 { … … 4739 4806 if (output == NULL) 4740 4807 return false; 4741 else 4808 else 4742 4809 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4743 4810 for (int step=startstep;step < endstep; step++) { // loop over all time steps -
Property mode
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
