Changeset 1b2aa1 for molecuilder/src/molecules.cpp
- Timestamp:
- Jul 23, 2009, 12:14:13 PM (16 years ago)
- Children:
- f39735
- Parents:
- a41b50
- File:
-
- 1 edited
-
molecuilder/src/molecules.cpp (modified) (90 diffs)
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/molecules.cpp
ra41b50 r1b2aa1 16 16 double LSQ (const gsl_vector * x, void * params) 17 17 { 18 double sum = 0.;19 struct LSQ_params *par = (struct LSQ_params *)params;20 Vector **vectors = par->vectors;21 int num = par->num;22 23 for (int i=num;i--;) {24 for(int j=NDIM;j--;)25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]);26 }27 28 return sum;18 double sum = 0.; 19 struct LSQ_params *par = (struct LSQ_params *)params; 20 Vector **vectors = par->vectors; 21 int num = par->num; 22 23 for (int i=num;i--;) { 24 for(int j=NDIM;j--;) 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 } 27 28 return sum; 29 29 }; 30 30 … … 36 36 molecule::molecule(periodentafel *teil) 37 37 { 38 // init atom chain list39 start = new atom;40 end = new atom;41 start->father = NULL;42 end->father = NULL;43 link(start,end);44 // init bond chain list45 first = new bond(start, end, 1, -1);46 last = new bond(start, end, 1, -1);47 link(first,last);48 // other stuff49 MDSteps = 0;50 last_atom = 0;51 elemente = teil;52 AtomCount = 0;53 BondCount = 0;54 NoNonBonds = 0;55 NoNonHydrogen = 0;56 NoCyclicBonds = 0;57 ListOfBondsPerAtom = NULL;58 NumberOfBondsPerAtom = NULL;59 ElementCount = 0;60 for(int i=MAX_ELEMENTS;i--;)61 ElementsInMolecule[i] = 0;62 cell_size[0] = cell_size[2] = cell_size[5]= 20.;63 cell_size[1] = cell_size[3] = cell_size[4]= 0.;64 strcpy(name,"none");65 IndexNr = -1;66 ActiveFlag = false;38 // init atom chain list 39 start = new atom; 40 end = new atom; 41 start->father = NULL; 42 end->father = NULL; 43 link(start,end); 44 // init bond chain list 45 first = new bond(start, end, 1, -1); 46 last = new bond(start, end, 1, -1); 47 link(first,last); 48 // other stuff 49 MDSteps = 0; 50 last_atom = 0; 51 elemente = teil; 52 AtomCount = 0; 53 BondCount = 0; 54 NoNonBonds = 0; 55 NoNonHydrogen = 0; 56 NoCyclicBonds = 0; 57 ListOfBondsPerAtom = NULL; 58 NumberOfBondsPerAtom = NULL; 59 ElementCount = 0; 60 for(int i=MAX_ELEMENTS;i--;) 61 ElementsInMolecule[i] = 0; 62 cell_size[0] = cell_size[2] = cell_size[5]= 20.; 63 cell_size[1] = cell_size[3] = cell_size[4]= 0.; 64 strcpy(name,"none"); 65 IndexNr = -1; 66 ActiveFlag = false; 67 67 }; 68 68 … … 72 72 molecule::~molecule() 73 73 { 74 if (ListOfBondsPerAtom != NULL)75 for(int i=AtomCount;i--;)76 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");77 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");78 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");79 CleanupMolecule();80 delete(first);81 delete(last);82 delete(end);83 delete(start);74 if (ListOfBondsPerAtom != NULL) 75 for(int i=AtomCount;i--;) 76 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]"); 77 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom"); 78 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom"); 79 CleanupMolecule(); 80 delete(first); 81 delete(last); 82 delete(end); 83 delete(start); 84 84 }; 85 85 … … 91 91 bool molecule::AddAtom(atom *pointer) 92 92 { 93 if (pointer != NULL) {94 pointer->sort = &pointer->nr;95 pointer->nr = last_atom++;// increase number within molecule96 AtomCount++;97 if (pointer->type != NULL) {98 if (ElementsInMolecule[pointer->type->Z] == 0)99 ElementCount++;100 ElementsInMolecule[pointer->type->Z]++; // increase number of elements101 if (pointer->type->Z != 1)102 NoNonHydrogen++;103 if (pointer->Name == NULL) {104 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");105 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");106 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);107 }108 }109 return add(pointer, end);110 } else111 return false;93 if (pointer != NULL) { 94 pointer->sort = &pointer->nr; 95 pointer->nr = last_atom++; // increase number within molecule 96 AtomCount++; 97 if (pointer->type != NULL) { 98 if (ElementsInMolecule[pointer->type->Z] == 0) 99 ElementCount++; 100 ElementsInMolecule[pointer->type->Z]++; // increase number of elements 101 if (pointer->type->Z != 1) 102 NoNonHydrogen++; 103 if (pointer->Name == NULL) { 104 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name"); 105 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name"); 106 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1); 107 } 108 } 109 return add(pointer, end); 110 } else 111 return false; 112 112 }; 113 113 … … 119 119 atom * molecule::AddCopyAtom(atom *pointer) 120 120 { 121 if (pointer != NULL) {122 atom *walker = new atom();123 walker->type = pointer->type;// copy element of atom124 walker->x.CopyVector(&pointer->x); // copy coordination125 walker->v.CopyVector(&pointer->v); // copy velocity126 walker->FixedIon = pointer->FixedIon;127 walker->sort = &walker->nr;128 walker->nr = last_atom++;// increase number within molecule129 walker->father = pointer; //->GetTrueFather();130 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");131 strcpy (walker->Name, pointer->Name);132 add(walker, end);133 if ((pointer->type != NULL) && (pointer->type->Z != 1))134 NoNonHydrogen++;135 AtomCount++;136 return walker;137 } else138 return NULL;121 if (pointer != NULL) { 122 atom *walker = new atom(); 123 walker->type = pointer->type; // copy element of atom 124 walker->x.CopyVector(&pointer->x); // copy coordination 125 walker->v.CopyVector(&pointer->v); // copy velocity 126 walker->FixedIon = pointer->FixedIon; 127 walker->sort = &walker->nr; 128 walker->nr = last_atom++; // increase number within molecule 129 walker->father = pointer; //->GetTrueFather(); 130 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name"); 131 strcpy (walker->Name, pointer->Name); 132 add(walker, end); 133 if ((pointer->type != NULL) && (pointer->type->Z != 1)) 134 NoNonHydrogen++; 135 AtomCount++; 136 return walker; 137 } else 138 return NULL; 139 139 }; 140 140 … … 144 144 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 145 145 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 146 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().147 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two148 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the149 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two150 * hydrogens forming this angle with *origin.146 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 147 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 148 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 149 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 150 * hydrogens forming this angle with *origin. 151 151 * -# Triple Bond: The idea is to set up a tetraoid (C1-H1-H2-H3) (however the lengths \f$b\f$ of the sides of the base 152 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be153 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):154 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).155 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}}156 * \f]157 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates158 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.159 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that160 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1.161 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}162 * \f]163 * as the coordination of all three atoms in the coordinate system of these three vectors:164 * \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$.152 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 153 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 154 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 155 * \f[ h = l \cdot \cos{\left (\frac{\alpha}{2} \right )} \qquad b = 2l \cdot \sin{\left (\frac{\alpha}{2} \right)} \quad \rightarrow \quad d = l \cdot \sqrt{\cos^2{\left (\frac{\alpha}{2} \right)}-\frac{1}{3}\cdot\sin^2{\left (\frac{\alpha}{2}\right )}} 156 * \f] 157 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 158 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 159 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 160 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 161 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 162 * \f] 163 * as the coordination of all three atoms in the coordinate system of these three vectors: 164 * \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$. 165 165 * 166 166 * \param *out output stream for debugging … … 170 170 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 171 171 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds) 172 * \param NumBond number of bonds in \a **BondList172 * \param NumBond number of bonds in \a **BondList 173 173 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 174 174 * \return number of atoms added, if < bond::BondDegree then something went wrong … … 177 177 bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem) 178 178 { 179 double bondlength;// bond length of the bond to be replaced/cut180 double bondangle;// bond angle of the bond to be replaced/cut181 double BondRescale;// rescale value for the hydrogen bond length182 bool AllWentWell = true;// flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit183 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane184 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added185 double b,l,d,f,g, alpha, factors[NDIM];// hold temporary values in triple bond case for coordination determination186 Vector Orthovector1, Orthovector2;// temporary vectors in coordination construction187 Vector InBondvector;// vector in direction of *Bond188 bond *Binder = NULL;189 double *matrix;190 191 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;192 // create vector in direction of bond193 InBondvector.CopyVector(&TopReplacement->x);194 InBondvector.SubtractVector(&TopOrigin->x);195 bondlength = InBondvector.Norm();196 197 // is greater than typical bond distance? Then we have to correct periodically198 // the problem is not the H being out of the box, but InBondvector have the wrong direction199 // due to TopReplacement or Origin being on the wrong side!200 if (bondlength > BondDistance) {201 // *out << Verbose(4) << "InBondvector is: ";202 // InBondvector.Output(out);203 // *out << endl;204 Orthovector1.Zero();205 for (int i=NDIM;i--;) {206 l = TopReplacement->x.x[i] - TopOrigin->x.x[i];207 if (fabs(l) > BondDistance) { // is component greater than bond distance208 Orthovector1.x[i] = (l < 0) ? -1. : +1.;209 } // (signs are correct, was tested!)210 }211 matrix = ReturnFullMatrixforSymmetric(cell_size);212 Orthovector1.MatrixMultiplication(matrix);213 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation214 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");215 bondlength = InBondvector.Norm();216 // *out << Verbose(4) << "Corrected InBondvector is now: ";217 // InBondvector.Output(out);218 // *out << endl;219 } // periodic correction finished220 221 InBondvector.Normalize();222 // get typical bond length and store as scale factor for later223 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];224 if (BondRescale == -1) {225 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;226 return false;227 BondRescale = bondlength;228 } else {229 if (!IsAngstroem)230 BondRescale /= (1.*AtomicLengthToAngstroem);231 }232 233 // discern single, double and triple bonds234 switch(TopBond->BondDegree) {235 case 1:236 FirstOtherAtom = new atom();// new atom237 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen238 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity239 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;240 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen241 FirstOtherAtom->father = TopReplacement;242 BondRescale = bondlength;243 } else {244 FirstOtherAtom->father = NULL;// if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father245 }246 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length247 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...248 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom249 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);250 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";251 // FirstOtherAtom->x.Output(out);252 // *out << endl;253 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);254 Binder->Cyclic = false;255 Binder->Type = TreeEdge;256 break;257 case 2:258 // determine two other bonds (warning if there are more than two other) plus valence sanity check259 for (int i=0;i<NumBond;i++) {260 if (BondList[i] != TopBond) {261 if (FirstBond == NULL) {262 FirstBond = BondList[i];263 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);264 } else if (SecondBond == NULL) {265 SecondBond = BondList[i];266 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);267 } else {268 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;269 }270 }271 }272 if (SecondOtherAtom == NULL) {// then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond)273 SecondBond = TopBond;274 SecondOtherAtom = TopReplacement;275 }276 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all277 // *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;278 279 // determine the plane of these two with the *origin280 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);281 } else {282 Orthovector1.GetOneNormalVector(&InBondvector);283 }284 //*out << Verbose(3)<< "Orthovector1: ";285 //Orthovector1.Output(out);286 //*out << endl;287 // orthogonal vector and bond vector between origin and replacement form the new plane288 Orthovector1.MakeNormalVector(&InBondvector);289 Orthovector1.Normalize();290 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;291 292 // create the two Hydrogens ...293 FirstOtherAtom = new atom();294 SecondOtherAtom = new atom();295 FirstOtherAtom->type = elemente->FindElement(1);296 SecondOtherAtom->type = elemente->FindElement(1);297 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity298 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;299 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity300 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;301 FirstOtherAtom->father = NULL;// we are just an added hydrogen with no father302 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father303 bondangle = TopOrigin->type->HBondAngle[1];304 if (bondangle == -1) {305 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;306 return false;307 bondangle = 0;308 }309 bondangle *= M_PI/180./2.;310 // *out << Verbose(3) << "ReScaleCheck: InBondvector ";311 // InBondvector.Output(out);312 // *out << endl;313 // *out << Verbose(3) << "ReScaleCheck: Orthovector ";314 // Orthovector1.Output(out);315 // *out << endl;316 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;317 FirstOtherAtom->x.Zero();318 SecondOtherAtom->x.Zero();319 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)320 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));321 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));322 }323 FirstOtherAtom->x.Scale(&BondRescale);// rescale by correct BondDistance324 SecondOtherAtom->x.Scale(&BondRescale);325 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;326 for(int i=NDIM;i--;) { // and make relative to origin atom327 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];328 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];329 }330 // ... and add to molecule331 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);332 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);333 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";334 // FirstOtherAtom->x.Output(out);335 // *out << endl;336 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";337 // SecondOtherAtom->x.Output(out);338 // *out << endl;339 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);340 Binder->Cyclic = false;341 Binder->Type = TreeEdge;342 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);343 Binder->Cyclic = false;344 Binder->Type = TreeEdge;345 break;346 case 3:347 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)348 FirstOtherAtom = new atom();349 SecondOtherAtom = new atom();350 ThirdOtherAtom = new atom();351 FirstOtherAtom->type = elemente->FindElement(1);352 SecondOtherAtom->type = elemente->FindElement(1);353 ThirdOtherAtom->type = elemente->FindElement(1);354 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity355 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;356 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity357 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;358 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity359 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;360 FirstOtherAtom->father = NULL; //we are just an added hydrogen with no father361 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father362 ThirdOtherAtom->father = NULL; //we are just an added hydrogen with no father363 364 // we need to vectors orthonormal the InBondvector365 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);366 // *out << Verbose(3) << "Orthovector1: ";367 // Orthovector1.Output(out);368 // *out << endl;369 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);370 // *out << Verbose(3) << "Orthovector2: ";371 // Orthovector2.Output(out);372 // *out << endl;373 374 // create correct coordination for the three atoms375 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;// retrieve triple bond angle from database376 l = BondRescale;// desired bond length377 b = 2.*l*sin(alpha);// base length of isosceles triangle378 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);// length for InBondvector379 f = b/sqrt(3.);// length for Orthvector1380 g = b/2.;// length for Orthvector2381 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;382 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", "<< sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl;383 factors[0] = d;384 factors[1] = f;385 factors[2] = 0.;386 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);387 factors[1] = -0.5*f;388 factors[2] = g;389 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);390 factors[2] = -g;391 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);392 393 // rescale each to correct BondDistance394 // FirstOtherAtom->x.Scale(&BondRescale);395 // SecondOtherAtom->x.Scale(&BondRescale);396 // ThirdOtherAtom->x.Scale(&BondRescale);397 398 // and relative to *origin atom399 FirstOtherAtom->x.AddVector(&TopOrigin->x);400 SecondOtherAtom->x.AddVector(&TopOrigin->x);401 ThirdOtherAtom->x.AddVector(&TopOrigin->x);402 403 // ... and add to molecule404 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);405 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);406 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);407 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";408 // FirstOtherAtom->x.Output(out);409 // *out << endl;410 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";411 // SecondOtherAtom->x.Output(out);412 // *out << endl;413 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";414 // ThirdOtherAtom->x.Output(out);415 // *out << endl;416 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);417 Binder->Cyclic = false;418 Binder->Type = TreeEdge;419 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);420 Binder->Cyclic = false;421 Binder->Type = TreeEdge;422 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);423 Binder->Cyclic = false;424 Binder->Type = TreeEdge;425 break;426 default:427 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;428 AllWentWell = false;429 break;430 }431 432 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;433 return AllWentWell;179 double bondlength; // bond length of the bond to be replaced/cut 180 double bondangle; // bond angle of the bond to be replaced/cut 181 double BondRescale; // rescale value for the hydrogen bond length 182 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 183 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane 184 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 185 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 186 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 187 Vector InBondvector; // vector in direction of *Bond 188 bond *Binder = NULL; 189 double *matrix; 190 191 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl; 192 // create vector in direction of bond 193 InBondvector.CopyVector(&TopReplacement->x); 194 InBondvector.SubtractVector(&TopOrigin->x); 195 bondlength = InBondvector.Norm(); 196 197 // is greater than typical bond distance? Then we have to correct periodically 198 // the problem is not the H being out of the box, but InBondvector have the wrong direction 199 // due to TopReplacement or Origin being on the wrong side! 200 if (bondlength > BondDistance) { 201 // *out << Verbose(4) << "InBondvector is: "; 202 // InBondvector.Output(out); 203 // *out << endl; 204 Orthovector1.Zero(); 205 for (int i=NDIM;i--;) { 206 l = TopReplacement->x.x[i] - TopOrigin->x.x[i]; 207 if (fabs(l) > BondDistance) { // is component greater than bond distance 208 Orthovector1.x[i] = (l < 0) ? -1. : +1.; 209 } // (signs are correct, was tested!) 210 } 211 matrix = ReturnFullMatrixforSymmetric(cell_size); 212 Orthovector1.MatrixMultiplication(matrix); 213 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation 214 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix"); 215 bondlength = InBondvector.Norm(); 216 // *out << Verbose(4) << "Corrected InBondvector is now: "; 217 // InBondvector.Output(out); 218 // *out << endl; 219 } // periodic correction finished 220 221 InBondvector.Normalize(); 222 // get typical bond length and store as scale factor for later 223 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 224 if (BondRescale == -1) { 225 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 226 return false; 227 BondRescale = bondlength; 228 } else { 229 if (!IsAngstroem) 230 BondRescale /= (1.*AtomicLengthToAngstroem); 231 } 232 233 // discern single, double and triple bonds 234 switch(TopBond->BondDegree) { 235 case 1: 236 FirstOtherAtom = new atom(); // new atom 237 FirstOtherAtom->type = elemente->FindElement(1); // element is Hydrogen 238 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 239 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 240 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen 241 FirstOtherAtom->father = TopReplacement; 242 BondRescale = bondlength; 243 } else { 244 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 245 } 246 InBondvector.Scale(&BondRescale); // rescale the distance vector to Hydrogen bond length 247 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ... 248 FirstOtherAtom->x.AddVector(&InBondvector); // ... and add distance vector to replacement atom 249 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 250 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 251 // FirstOtherAtom->x.Output(out); 252 // *out << endl; 253 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 254 Binder->Cyclic = false; 255 Binder->Type = TreeEdge; 256 break; 257 case 2: 258 // determine two other bonds (warning if there are more than two other) plus valence sanity check 259 for (int i=0;i<NumBond;i++) { 260 if (BondList[i] != TopBond) { 261 if (FirstBond == NULL) { 262 FirstBond = BondList[i]; 263 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 264 } else if (SecondBond == NULL) { 265 SecondBond = BondList[i]; 266 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 267 } else { 268 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name; 269 } 270 } 271 } 272 if (SecondOtherAtom == NULL) { // then we have an atom with valence four, but only 3 bonds: one to replace and one which is TopBond (third is FirstBond) 273 SecondBond = TopBond; 274 SecondOtherAtom = TopReplacement; 275 } 276 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 277 // *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; 278 279 // determine the plane of these two with the *origin 280 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); 281 } else { 282 Orthovector1.GetOneNormalVector(&InBondvector); 283 } 284 //*out << Verbose(3)<< "Orthovector1: "; 285 //Orthovector1.Output(out); 286 //*out << endl; 287 // orthogonal vector and bond vector between origin and replacement form the new plane 288 Orthovector1.MakeNormalVector(&InBondvector); 289 Orthovector1.Normalize(); 290 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 291 292 // create the two Hydrogens ... 293 FirstOtherAtom = new atom(); 294 SecondOtherAtom = new atom(); 295 FirstOtherAtom->type = elemente->FindElement(1); 296 SecondOtherAtom->type = elemente->FindElement(1); 297 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 298 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 299 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 300 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 301 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 302 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 303 bondangle = TopOrigin->type->HBondAngle[1]; 304 if (bondangle == -1) { 305 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 306 return false; 307 bondangle = 0; 308 } 309 bondangle *= M_PI/180./2.; 310 // *out << Verbose(3) << "ReScaleCheck: InBondvector "; 311 // InBondvector.Output(out); 312 // *out << endl; 313 // *out << Verbose(3) << "ReScaleCheck: Orthovector "; 314 // Orthovector1.Output(out); 315 // *out << endl; 316 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl; 317 FirstOtherAtom->x.Zero(); 318 SecondOtherAtom->x.Zero(); 319 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 320 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle)); 321 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 322 } 323 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 324 SecondOtherAtom->x.Scale(&BondRescale); 325 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 326 for(int i=NDIM;i--;) { // and make relative to origin atom 327 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 328 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 329 } 330 // ... and add to molecule 331 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 332 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 333 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 334 // FirstOtherAtom->x.Output(out); 335 // *out << endl; 336 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 337 // SecondOtherAtom->x.Output(out); 338 // *out << endl; 339 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 340 Binder->Cyclic = false; 341 Binder->Type = TreeEdge; 342 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 343 Binder->Cyclic = false; 344 Binder->Type = TreeEdge; 345 break; 346 case 3: 347 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 348 FirstOtherAtom = new atom(); 349 SecondOtherAtom = new atom(); 350 ThirdOtherAtom = new atom(); 351 FirstOtherAtom->type = elemente->FindElement(1); 352 SecondOtherAtom->type = elemente->FindElement(1); 353 ThirdOtherAtom->type = elemente->FindElement(1); 354 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 355 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 356 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 357 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 358 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 359 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon; 360 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 361 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 362 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father 363 364 // we need to vectors orthonormal the InBondvector 365 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector); 366 // *out << Verbose(3) << "Orthovector1: "; 367 // Orthovector1.Output(out); 368 // *out << endl; 369 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 370 // *out << Verbose(3) << "Orthovector2: "; 371 // Orthovector2.Output(out); 372 // *out << endl; 373 374 // create correct coordination for the three atoms 375 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database 376 l = BondRescale; // desired bond length 377 b = 2.*l*sin(alpha); // base length of isosceles triangle 378 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 379 f = b/sqrt(3.); // length for Orthvector1 380 g = b/2.; // length for Orthvector2 381 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl; 382 // *out << Verbose(3) << "The three Bond lengths: " << sqrt(d*d+f*f) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << ", " << sqrt(d*d+(-0.5*f)*(-0.5*f)+g*g) << endl; 383 factors[0] = d; 384 factors[1] = f; 385 factors[2] = 0.; 386 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[1] = -0.5*f; 388 factors[2] = g; 389 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 390 factors[2] = -g; 391 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 392 393 // rescale each to correct BondDistance 394 // FirstOtherAtom->x.Scale(&BondRescale); 395 // SecondOtherAtom->x.Scale(&BondRescale); 396 // ThirdOtherAtom->x.Scale(&BondRescale); 397 398 // and relative to *origin atom 399 FirstOtherAtom->x.AddVector(&TopOrigin->x); 400 SecondOtherAtom->x.AddVector(&TopOrigin->x); 401 ThirdOtherAtom->x.AddVector(&TopOrigin->x); 402 403 // ... and add to molecule 404 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 405 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 406 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom); 407 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 408 // FirstOtherAtom->x.Output(out); 409 // *out << endl; 410 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 411 // SecondOtherAtom->x.Output(out); 412 // *out << endl; 413 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: "; 414 // ThirdOtherAtom->x.Output(out); 415 // *out << endl; 416 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 417 Binder->Cyclic = false; 418 Binder->Type = TreeEdge; 419 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 420 Binder->Cyclic = false; 421 Binder->Type = TreeEdge; 422 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1); 423 Binder->Cyclic = false; 424 Binder->Type = TreeEdge; 425 break; 426 default: 427 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl; 428 AllWentWell = false; 429 break; 430 } 431 432 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl; 433 return AllWentWell; 434 434 }; 435 435 … … 441 441 bool molecule::AddXYZFile(string filename) 442 442 { 443 istringstream *input = NULL;444 int NumberOfAtoms = 0; // atom number in xyz read445 int i, j; // loop variables446 atom *Walker = NULL;// pointer to added atom447 char shorthand[3];// shorthand for atom name448 ifstream xyzfile;// xyz file449 string line;// currently parsed line450 double x[3];// atom coordinates451 452 xyzfile.open(filename.c_str());453 if (!xyzfile)454 return false;455 456 getline(xyzfile,line,'\n'); // Read numer of atoms in file457 input = new istringstream(line);458 *input >> NumberOfAtoms;459 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;460 getline(xyzfile,line,'\n'); // Read comment461 cout << Verbose(1) << "Comment: " << line << endl;462 463 if (MDSteps == 0) // no atoms yet present464 MDSteps++;465 for(i=0;i<NumberOfAtoms;i++){466 Walker = new atom;467 getline(xyzfile,line,'\n');468 istringstream *item = new istringstream(line);469 //istringstream input(line);470 //cout << Verbose(1) << "Reading: " << line << endl;471 *item >> shorthand;472 *item >> x[0];473 *item >> x[1];474 *item >> x[2];475 Walker->type = elemente->FindElement(shorthand);476 if (Walker->type == NULL) {477 cerr << "Could not parse the element at line: '" << line << "', setting to H.";478 Walker->type = elemente->FindElement(1);479 }480 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {481 Trajectories[Walker].R.resize(MDSteps+10);482 Trajectories[Walker].U.resize(MDSteps+10);483 Trajectories[Walker].F.resize(MDSteps+10);484 }485 for(j=NDIM;j--;) {486 Walker->x.x[j] = x[j];487 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];488 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;489 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;490 }491 AddAtom(Walker);// add to molecule492 delete(item);493 }494 xyzfile.close();495 delete(input);496 return true;443 istringstream *input = NULL; 444 int NumberOfAtoms = 0; // atom number in xyz read 445 int i, j; // loop variables 446 atom *Walker = NULL; // pointer to added atom 447 char shorthand[3]; // shorthand for atom name 448 ifstream xyzfile; // xyz file 449 string line; // currently parsed line 450 double x[3]; // atom coordinates 451 452 xyzfile.open(filename.c_str()); 453 if (!xyzfile) 454 return false; 455 456 getline(xyzfile,line,'\n'); // Read numer of atoms in file 457 input = new istringstream(line); 458 *input >> NumberOfAtoms; 459 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 460 getline(xyzfile,line,'\n'); // Read comment 461 cout << Verbose(1) << "Comment: " << line << endl; 462 463 if (MDSteps == 0) // no atoms yet present 464 MDSteps++; 465 for(i=0;i<NumberOfAtoms;i++){ 466 Walker = new atom; 467 getline(xyzfile,line,'\n'); 468 istringstream *item = new istringstream(line); 469 //istringstream input(line); 470 //cout << Verbose(1) << "Reading: " << line << endl; 471 *item >> shorthand; 472 *item >> x[0]; 473 *item >> x[1]; 474 *item >> x[2]; 475 Walker->type = elemente->FindElement(shorthand); 476 if (Walker->type == NULL) { 477 cerr << "Could not parse the element at line: '" << line << "', setting to H."; 478 Walker->type = elemente->FindElement(1); 479 } 480 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) { 481 Trajectories[Walker].R.resize(MDSteps+10); 482 Trajectories[Walker].U.resize(MDSteps+10); 483 Trajectories[Walker].F.resize(MDSteps+10); 484 } 485 for(j=NDIM;j--;) { 486 Walker->x.x[j] = x[j]; 487 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j]; 488 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0; 489 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0; 490 } 491 AddAtom(Walker); // add to molecule 492 delete(item); 493 } 494 xyzfile.close(); 495 delete(input); 496 return true; 497 497 }; 498 498 … … 502 502 molecule *molecule::CopyMolecule() 503 503 { 504 molecule *copy = new molecule(elemente);505 atom *CurrentAtom = NULL;506 atom *LeftAtom = NULL, *RightAtom = NULL;507 atom *Walker = NULL;508 509 // copy all atoms510 Walker = start;511 while(Walker->next != end) {512 Walker = Walker->next;513 CurrentAtom = copy->AddCopyAtom(Walker);514 }515 516 // copy all bonds517 bond *Binder = first;518 bond *NewBond = NULL;519 while(Binder->next != last) {520 Binder = Binder->next;521 // get the pendant atoms of current bond in the copy molecule522 LeftAtom = copy->start;523 while (LeftAtom->next != copy->end) {524 LeftAtom = LeftAtom->next;525 if (LeftAtom->father == Binder->leftatom)526 break;527 }528 RightAtom = copy->start;529 while (RightAtom->next != copy->end) {530 RightAtom = RightAtom->next;531 if (RightAtom->father == Binder->rightatom)532 break;533 }534 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);535 NewBond->Cyclic = Binder->Cyclic;536 if (Binder->Cyclic)537 copy->NoCyclicBonds++;538 NewBond->Type = Binder->Type;539 }540 // correct fathers541 Walker = copy->start;542 while(Walker->next != copy->end) {543 Walker = Walker->next;544 if (Walker->father->father == Walker->father)// same atom in copy's father points to itself545 Walker->father = Walker;// set father to itself (copy of a whole molecule)546 else547 Walker->father = Walker->father->father;// set father to original's father548 }549 // copy values550 copy->CountAtoms((ofstream *)&cout);551 copy->CountElements();552 if (first->next != last) {// if adjaceny list is present553 copy->BondDistance = BondDistance;554 copy->CreateListOfBondsPerAtom((ofstream *)&cout);555 }556 557 return copy;504 molecule *copy = new molecule(elemente); 505 atom *CurrentAtom = NULL; 506 atom *LeftAtom = NULL, *RightAtom = NULL; 507 atom *Walker = NULL; 508 509 // copy all atoms 510 Walker = start; 511 while(Walker->next != end) { 512 Walker = Walker->next; 513 CurrentAtom = copy->AddCopyAtom(Walker); 514 } 515 516 // copy all bonds 517 bond *Binder = first; 518 bond *NewBond = NULL; 519 while(Binder->next != last) { 520 Binder = Binder->next; 521 // get the pendant atoms of current bond in the copy molecule 522 LeftAtom = copy->start; 523 while (LeftAtom->next != copy->end) { 524 LeftAtom = LeftAtom->next; 525 if (LeftAtom->father == Binder->leftatom) 526 break; 527 } 528 RightAtom = copy->start; 529 while (RightAtom->next != copy->end) { 530 RightAtom = RightAtom->next; 531 if (RightAtom->father == Binder->rightatom) 532 break; 533 } 534 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree); 535 NewBond->Cyclic = Binder->Cyclic; 536 if (Binder->Cyclic) 537 copy->NoCyclicBonds++; 538 NewBond->Type = Binder->Type; 539 } 540 // correct fathers 541 Walker = copy->start; 542 while(Walker->next != copy->end) { 543 Walker = Walker->next; 544 if (Walker->father->father == Walker->father) // same atom in copy's father points to itself 545 Walker->father = Walker; // set father to itself (copy of a whole molecule) 546 else 547 Walker->father = Walker->father->father; // set father to original's father 548 } 549 // copy values 550 copy->CountAtoms((ofstream *)&cout); 551 copy->CountElements(); 552 if (first->next != last) { // if adjaceny list is present 553 copy->BondDistance = BondDistance; 554 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 555 } 556 557 return copy; 558 558 }; 559 559 … … 566 566 bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1) 567 567 { 568 bond *Binder = NULL;569 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {570 Binder = new bond(atom1, atom2, degree, BondCount++);571 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))572 NoNonBonds++;573 add(Binder, last);574 } else {575 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl;576 }577 return Binder;568 bond *Binder = NULL; 569 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) { 570 Binder = new bond(atom1, atom2, degree, BondCount++); 571 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1)) 572 NoNonBonds++; 573 add(Binder, last); 574 } else { 575 cerr << Verbose(1) << "ERROR: Could not add bond between " << atom1->Name << " and " << atom2->Name << " as one or both are not present in the molecule." << endl; 576 } 577 return Binder; 578 578 }; 579 579 … … 585 585 bool molecule::RemoveBond(bond *pointer) 586 586 { 587 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;588 removewithoutcheck(pointer);589 return true;587 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 588 removewithoutcheck(pointer); 589 return true; 590 590 }; 591 591 … … 597 597 bool molecule::RemoveBonds(atom *BondPartner) 598 598 { 599 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;600 return false;599 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 600 return false; 601 601 }; 602 602 … … 622 622 void molecule::SetBoxDimension(Vector *dim) 623 623 { 624 cell_size[0] = dim->x[0];625 cell_size[1] = 0.;626 cell_size[2] = dim->x[1];627 cell_size[3] = 0.;628 cell_size[4] = 0.;629 cell_size[5] = dim->x[2];624 cell_size[0] = dim->x[0]; 625 cell_size[1] = 0.; 626 cell_size[2] = dim->x[1]; 627 cell_size[3] = 0.; 628 cell_size[4] = 0.; 629 cell_size[5] = dim->x[2]; 630 630 }; 631 631 … … 636 636 bool molecule::CenterInBox(ofstream *out, Vector *BoxLengths) 637 637 { 638 bool status = true;639 atom *ptr = NULL;640 Vector *min = new Vector;641 Vector *max = new Vector;642 643 // gather min and max for each axis644 ptr = start->next;// start at first in list645 if (ptr != end) {//list not empty?646 for (int i=NDIM;i--;) {647 max->x[i] = ptr->x.x[i];648 min->x[i] = ptr->x.x[i];649 }650 while (ptr->next != end) {// continue with second if present651 ptr = ptr->next;652 //ptr->Output(1,1,out);653 for (int i=NDIM;i--;) {654 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];655 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];656 }657 }658 }659 // sanity check660 for(int i=NDIM;i--;) {661 if (max->x[i] - min->x[i] > BoxLengths->x[i])662 status = false;663 }664 // warn if check failed665 if (!status)666 *out << "WARNING: molecule is bigger than defined box!" << endl;667 else {// else center in box668 max->AddVector(min);669 max->Scale(-1.);670 max->AddVector(BoxLengths);671 max->Scale(0.5);638 bool status = true; 639 atom *ptr = NULL; 640 Vector *min = new Vector; 641 Vector *max = new Vector; 642 643 // gather min and max for each axis 644 ptr = start->next; // start at first in list 645 if (ptr != end) { //list not empty? 646 for (int i=NDIM;i--;) { 647 max->x[i] = ptr->x.x[i]; 648 min->x[i] = ptr->x.x[i]; 649 } 650 while (ptr->next != end) { // continue with second if present 651 ptr = ptr->next; 652 //ptr->Output(1,1,out); 653 for (int i=NDIM;i--;) { 654 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 655 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 656 } 657 } 658 } 659 // sanity check 660 for(int i=NDIM;i--;) { 661 if (max->x[i] - min->x[i] > BoxLengths->x[i]) 662 status = false; 663 } 664 // warn if check failed 665 if (!status) 666 *out << "WARNING: molecule is bigger than defined box!" << endl; 667 else { // else center in box 668 max->AddVector(min); 669 max->Scale(-1.); 670 max->AddVector(BoxLengths); 671 max->Scale(0.5); 672 672 Translate(max); 673 673 Center.Zero(); 674 }675 676 // free and exit677 delete(min);678 delete(max);679 return status;674 } 675 676 // free and exit 677 delete(min); 678 delete(max); 679 return status; 680 680 }; 681 681 … … 686 686 void molecule::CenterEdge(ofstream *out, Vector *max) 687 687 { 688 Vector *min = new Vector;689 690 // *out << Verbose(3) << "Begin of CenterEdge." << endl;691 atom *ptr = start->next;// start at first in list692 if (ptr != end) {//list not empty?693 for (int i=NDIM;i--;) {694 max->x[i] = ptr->x.x[i];695 min->x[i] = ptr->x.x[i];696 }697 while (ptr->next != end) {// continue with second if present698 ptr = ptr->next;699 //ptr->Output(1,1,out);700 for (int i=NDIM;i--;) {701 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];702 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];703 }704 }705 // *out << Verbose(4) << "Maximum is ";706 // max->Output(out);707 // *out << ", Minimum is ";708 // min->Output(out);709 // *out << endl;710 min->Scale(-1.);711 max->AddVector(min);712 Translate(min);713 Center.Zero();714 }715 delete(min);716 // *out << Verbose(3) << "End of CenterEdge." << endl;688 Vector *min = new Vector; 689 690 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 691 atom *ptr = start->next; // start at first in list 692 if (ptr != end) { //list not empty? 693 for (int i=NDIM;i--;) { 694 max->x[i] = ptr->x.x[i]; 695 min->x[i] = ptr->x.x[i]; 696 } 697 while (ptr->next != end) { // continue with second if present 698 ptr = ptr->next; 699 //ptr->Output(1,1,out); 700 for (int i=NDIM;i--;) { 701 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 702 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 703 } 704 } 705 // *out << Verbose(4) << "Maximum is "; 706 // max->Output(out); 707 // *out << ", Minimum is "; 708 // min->Output(out); 709 // *out << endl; 710 min->Scale(-1.); 711 max->AddVector(min); 712 Translate(min); 713 Center.Zero(); 714 } 715 delete(min); 716 // *out << Verbose(3) << "End of CenterEdge." << endl; 717 717 }; 718 718 … … 723 723 void molecule::CenterOrigin(ofstream *out) 724 724 { 725 int Num = 0;726 atom *ptr = start->next;// start at first in list727 728 Center.Zero();729 730 if (ptr != end) {//list not empty?731 while (ptr->next != end) {// continue with second if present732 ptr = ptr->next;733 Num++;734 Center.AddVector(&ptr->x);735 }736 Center.Scale(-1./Num); // divide through total number (and sign for direction)737 Translate(&Center);738 Center.Zero();739 }725 int Num = 0; 726 atom *ptr = start->next; // start at first in list 727 728 Center.Zero(); 729 730 if (ptr != end) { //list not empty? 731 while (ptr->next != end) { // continue with second if present 732 ptr = ptr->next; 733 Num++; 734 Center.AddVector(&ptr->x); 735 } 736 Center.Scale(-1./Num); // divide through total number (and sign for direction) 737 Translate(&Center); 738 Center.Zero(); 739 } 740 740 }; 741 741 … … 746 746 Vector * molecule::DetermineCenterOfAll(ofstream *out) 747 747 { 748 atom *ptr = start->next;// start at first in list749 Vector *a = new Vector();750 Vector tmp;751 double Num = 0;752 753 a->Zero();754 755 if (ptr != end) {//list not empty?756 while (ptr->next != end) {// continue with second if present757 ptr = ptr->next;758 Num += 1.;759 tmp.CopyVector(&ptr->x);760 a->AddVector(&tmp);761 }762 a->Scale(-1./Num); // divide through total mass (and sign for direction)763 }764 //cout << Verbose(1) << "Resulting center of gravity: ";765 //a->Output(out);766 //cout << endl;767 return a;748 atom *ptr = start->next; // start at first in list 749 Vector *a = new Vector(); 750 Vector tmp; 751 double Num = 0; 752 753 a->Zero(); 754 755 if (ptr != end) { //list not empty? 756 while (ptr->next != end) { // continue with second if present 757 ptr = ptr->next; 758 Num += 1.; 759 tmp.CopyVector(&ptr->x); 760 a->AddVector(&tmp); 761 } 762 a->Scale(-1./Num); // divide through total mass (and sign for direction) 763 } 764 //cout << Verbose(1) << "Resulting center of gravity: "; 765 //a->Output(out); 766 //cout << endl; 767 return a; 768 768 }; 769 769 … … 774 774 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 775 775 { 776 atom *ptr = start->next;// start at first in list777 Vector *a = new Vector();778 Vector tmp;779 double Num = 0;780 781 a->Zero();782 783 if (ptr != end) {//list not empty?784 while (ptr->next != end) {// continue with second if present785 ptr = ptr->next;786 Num += ptr->type->mass;787 tmp.CopyVector(&ptr->x);788 tmp.Scale(ptr->type->mass);// scale by mass789 a->AddVector(&tmp);790 }791 a->Scale(-1./Num); // divide through total mass (and sign for direction)792 }793 // *out << Verbose(1) << "Resulting center of gravity: ";794 // a->Output(out);795 // *out << endl;796 return a;776 atom *ptr = start->next; // start at first in list 777 Vector *a = new Vector(); 778 Vector tmp; 779 double Num = 0; 780 781 a->Zero(); 782 783 if (ptr != end) { //list not empty? 784 while (ptr->next != end) { // continue with second if present 785 ptr = ptr->next; 786 Num += ptr->type->mass; 787 tmp.CopyVector(&ptr->x); 788 tmp.Scale(ptr->type->mass); // scale by mass 789 a->AddVector(&tmp); 790 } 791 a->Scale(-1./Num); // divide through total mass (and sign for direction) 792 } 793 // *out << Verbose(1) << "Resulting center of gravity: "; 794 // a->Output(out); 795 // *out << endl; 796 return a; 797 797 }; 798 798 … … 803 803 void molecule::CenterPeriodic(ofstream *out) 804 804 { 805 DeterminePeriodicCenter(Center);805 DeterminePeriodicCenter(Center); 806 806 }; 807 807 … … 820 820 void molecule::Scale(double **factor) 821 821 { 822 atom *ptr = start;823 824 while (ptr->next != end) {825 ptr = ptr->next;826 for (int j=0;j<MDSteps;j++)827 Trajectories[ptr].R.at(j).Scale(factor);828 ptr->x.Scale(factor);829 }822 atom *ptr = start; 823 824 while (ptr->next != end) { 825 ptr = ptr->next; 826 for (int j=0;j<MDSteps;j++) 827 Trajectories[ptr].R.at(j).Scale(factor); 828 ptr->x.Scale(factor); 829 } 830 830 }; 831 831 … … 835 835 void molecule::Translate(const Vector *trans) 836 836 { 837 atom *ptr = start;838 839 while (ptr->next != end) {840 ptr = ptr->next;841 for (int j=0;j<MDSteps;j++)842 Trajectories[ptr].R.at(j).Translate(trans);843 ptr->x.Translate(trans);844 }837 atom *ptr = start; 838 839 while (ptr->next != end) { 840 ptr = ptr->next; 841 for (int j=0;j<MDSteps;j++) 842 Trajectories[ptr].R.at(j).Translate(trans); 843 ptr->x.Translate(trans); 844 } 845 845 }; 846 846 … … 850 850 void molecule::Mirror(const Vector *n) 851 851 { 852 atom *ptr = start;853 854 while (ptr->next != end) {855 ptr = ptr->next;856 for (int j=0;j<MDSteps;j++)857 Trajectories[ptr].R.at(j).Mirror(n);858 ptr->x.Mirror(n);859 }852 atom *ptr = start; 853 854 while (ptr->next != end) { 855 ptr = ptr->next; 856 for (int j=0;j<MDSteps;j++) 857 Trajectories[ptr].R.at(j).Mirror(n); 858 ptr->x.Mirror(n); 859 } 860 860 }; 861 861 … … 865 865 void molecule::DeterminePeriodicCenter(Vector ¢er) 866 866 { 867 atom *Walker = start;868 bond *Binder = NULL;869 double *matrix = ReturnFullMatrixforSymmetric(cell_size);870 double tmp;871 bool flag;872 Vector Testvector, Translationvector;873 874 do {875 center.Zero();876 flag = true;877 while (Walker->next != end) {878 Walker = Walker->next;867 atom *Walker = start; 868 bond *Binder = NULL; 869 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 870 double tmp; 871 bool flag; 872 Vector Testvector, Translationvector; 873 874 do { 875 center.Zero(); 876 flag = true; 877 while (Walker->next != end) { 878 Walker = Walker->next; 879 879 #ifdef ADDHYDROGEN 880 if (Walker->type->Z != 1) {880 if (Walker->type->Z != 1) { 881 881 #endif 882 Testvector.CopyVector(&Walker->x);883 Testvector.InverseMatrixMultiplication(matrix);884 Translationvector.Zero();885 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {886 Binder = ListOfBondsPerAtom[Walker->nr][i];887 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing888 for (int j=0;j<NDIM;j++) {889 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];890 if ((fabs(tmp)) > BondDistance) {891 flag = false;892 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;893 if (tmp > 0)894 Translationvector.x[j] -= 1.;895 else896 Translationvector.x[j] += 1.;897 }898 }899 }900 Testvector.AddVector(&Translationvector);901 Testvector.MatrixMultiplication(matrix);902 center.AddVector(&Testvector);903 cout << Verbose(1) << "vector is: ";904 Testvector.Output((ofstream *)&cout);905 cout << endl;882 Testvector.CopyVector(&Walker->x); 883 Testvector.InverseMatrixMultiplication(matrix); 884 Translationvector.Zero(); 885 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 886 Binder = ListOfBondsPerAtom[Walker->nr][i]; 887 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 888 for (int j=0;j<NDIM;j++) { 889 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 890 if ((fabs(tmp)) > BondDistance) { 891 flag = false; 892 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 893 if (tmp > 0) 894 Translationvector.x[j] -= 1.; 895 else 896 Translationvector.x[j] += 1.; 897 } 898 } 899 } 900 Testvector.AddVector(&Translationvector); 901 Testvector.MatrixMultiplication(matrix); 902 center.AddVector(&Testvector); 903 cout << Verbose(1) << "vector is: "; 904 Testvector.Output((ofstream *)&cout); 905 cout << endl; 906 906 #ifdef ADDHYDROGEN 907 // now also change all hydrogens908 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {909 Binder = ListOfBondsPerAtom[Walker->nr][i];910 if (Binder->GetOtherAtom(Walker)->type->Z == 1) {911 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);912 Testvector.InverseMatrixMultiplication(matrix);913 Testvector.AddVector(&Translationvector);914 Testvector.MatrixMultiplication(matrix);915 center.AddVector(&Testvector);916 cout << Verbose(1) << "Hydrogen vector is: ";917 Testvector.Output((ofstream *)&cout);918 cout << endl;919 }920 }921 }907 // now also change all hydrogens 908 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 909 Binder = ListOfBondsPerAtom[Walker->nr][i]; 910 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 911 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 912 Testvector.InverseMatrixMultiplication(matrix); 913 Testvector.AddVector(&Translationvector); 914 Testvector.MatrixMultiplication(matrix); 915 center.AddVector(&Testvector); 916 cout << Verbose(1) << "Hydrogen vector is: "; 917 Testvector.Output((ofstream *)&cout); 918 cout << endl; 919 } 920 } 921 } 922 922 #endif 923 }924 } while (!flag);925 Free((void **)&matrix, "molecule::DetermineCenter: *matrix");926 center.Scale(1./(double)AtomCount);923 } 924 } while (!flag); 925 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 926 center.Scale(1./(double)AtomCount); 927 927 }; 928 928 … … 933 933 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 934 934 { 935 atom *ptr = start;// start at first in list936 double InertiaTensor[NDIM*NDIM];937 Vector *CenterOfGravity = DetermineCenterOfGravity(out);938 939 CenterAtVector(out, CenterOfGravity);940 941 // reset inertia tensor942 for(int i=0;i<NDIM*NDIM;i++)943 InertiaTensor[i] = 0.;944 945 // sum up inertia tensor946 while (ptr->next != end) {947 ptr = ptr->next;948 Vector x;949 x.CopyVector(&ptr->x);950 //x.SubtractVector(CenterOfGravity);951 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);952 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);953 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);954 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);955 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);956 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);957 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);958 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);959 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);960 }961 // print InertiaTensor for debugging962 *out << "The inertia tensor is:" << endl;963 for(int i=0;i<NDIM;i++) {964 for(int j=0;j<NDIM;j++)965 *out << InertiaTensor[i*NDIM+j] << " ";966 *out << endl;967 }968 *out << endl;969 970 // diagonalize to determine principal axis system971 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);972 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);973 gsl_vector *eval = gsl_vector_alloc(NDIM);974 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);975 gsl_eigen_symmv(&m.matrix, eval, evec, T);976 gsl_eigen_symmv_free(T);977 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);978 979 for(int i=0;i<NDIM;i++) {980 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);981 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;982 }983 984 // check whether we rotate or not985 if (DoRotate) {986 *out << Verbose(1) << "Transforming molecule into PAS ... ";987 // the eigenvectors specify the transformation matrix988 ptr = start;989 while (ptr->next != end) {990 ptr = ptr->next;991 for (int j=0;j<MDSteps;j++)992 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);993 ptr->x.MatrixMultiplication(evec->data);994 }995 *out << "done." << endl;996 997 // summing anew for debugging (resulting matrix has to be diagonal!)998 // reset inertia tensor999 for(int i=0;i<NDIM*NDIM;i++)1000 InertiaTensor[i] = 0.;1001 1002 // sum up inertia tensor1003 ptr = start;1004 while (ptr->next != end) {1005 ptr = ptr->next;1006 Vector x;1007 x.CopyVector(&ptr->x);1008 //x.SubtractVector(CenterOfGravity);1009 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);1010 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);1011 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);1012 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);1013 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);1014 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);1015 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);1016 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);1017 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);1018 }1019 // print InertiaTensor for debugging1020 *out << "The inertia tensor is:" << endl;1021 for(int i=0;i<NDIM;i++) {1022 for(int j=0;j<NDIM;j++)1023 *out << InertiaTensor[i*NDIM+j] << " ";1024 *out << endl;1025 }1026 *out << endl;1027 }1028 1029 // free everything1030 delete(CenterOfGravity);1031 gsl_vector_free(eval);1032 gsl_matrix_free(evec);935 atom *ptr = start; // start at first in list 936 double InertiaTensor[NDIM*NDIM]; 937 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 938 939 CenterAtVector(out, CenterOfGravity); 940 941 // reset inertia tensor 942 for(int i=0;i<NDIM*NDIM;i++) 943 InertiaTensor[i] = 0.; 944 945 // sum up inertia tensor 946 while (ptr->next != end) { 947 ptr = ptr->next; 948 Vector x; 949 x.CopyVector(&ptr->x); 950 //x.SubtractVector(CenterOfGravity); 951 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 952 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 953 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 954 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 955 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 956 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 957 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 958 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 959 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 960 } 961 // print InertiaTensor for debugging 962 *out << "The inertia tensor is:" << endl; 963 for(int i=0;i<NDIM;i++) { 964 for(int j=0;j<NDIM;j++) 965 *out << InertiaTensor[i*NDIM+j] << " "; 966 *out << endl; 967 } 968 *out << endl; 969 970 // diagonalize to determine principal axis system 971 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); 972 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM); 973 gsl_vector *eval = gsl_vector_alloc(NDIM); 974 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM); 975 gsl_eigen_symmv(&m.matrix, eval, evec, T); 976 gsl_eigen_symmv_free(T); 977 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 978 979 for(int i=0;i<NDIM;i++) { 980 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 981 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 982 } 983 984 // check whether we rotate or not 985 if (DoRotate) { 986 *out << Verbose(1) << "Transforming molecule into PAS ... "; 987 // the eigenvectors specify the transformation matrix 988 ptr = start; 989 while (ptr->next != end) { 990 ptr = ptr->next; 991 for (int j=0;j<MDSteps;j++) 992 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 993 ptr->x.MatrixMultiplication(evec->data); 994 } 995 *out << "done." << endl; 996 997 // summing anew for debugging (resulting matrix has to be diagonal!) 998 // reset inertia tensor 999 for(int i=0;i<NDIM*NDIM;i++) 1000 InertiaTensor[i] = 0.; 1001 1002 // sum up inertia tensor 1003 ptr = start; 1004 while (ptr->next != end) { 1005 ptr = ptr->next; 1006 Vector x; 1007 x.CopyVector(&ptr->x); 1008 //x.SubtractVector(CenterOfGravity); 1009 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1010 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1011 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1012 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1013 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1014 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1015 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1016 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1017 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1018 } 1019 // print InertiaTensor for debugging 1020 *out << "The inertia tensor is:" << endl; 1021 for(int i=0;i<NDIM;i++) { 1022 for(int j=0;j<NDIM;j++) 1023 *out << InertiaTensor[i*NDIM+j] << " "; 1024 *out << endl; 1025 } 1026 *out << endl; 1027 } 1028 1029 // free everything 1030 delete(CenterOfGravity); 1031 gsl_vector_free(eval); 1032 gsl_matrix_free(evec); 1033 1033 }; 1034 1034 … … 1044 1044 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1045 1045 { 1046 element *runner = elemente->start;1047 atom *walker = NULL;1048 int AtomNo;1049 ifstream input(file);1050 string token;1051 stringstream item;1052 double a, IonMass;1053 ForceMatrix Force;1054 Vector tmpvector;1055 1056 CountElements();// make sure ElementsInMolecule is up to date1057 1058 // check file1059 if (input == NULL) {1060 return false;1061 } else {1062 // parse file into ForceMatrix1063 if (!Force.ParseMatrix(file, 0,0,0)) {1064 cerr << "Could not parse Force Matrix file " << file << "." << endl;1065 return false;1066 }1067 if (Force.RowCounter[0] != AtomCount) {1068 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;1069 return false;1070 }1071 // correct Forces1072 // for(int d=0;d<NDIM;d++)1073 // tmpvector.x[d] = 0.;1074 // for(int i=0;i<AtomCount;i++)1075 // for(int d=0;d<NDIM;d++) {1076 // tmpvector.x[d] += Force.Matrix[0][i][d+5];1077 // }1078 // for(int i=0;i<AtomCount;i++)1079 // for(int d=0;d<NDIM;d++) {1080 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;1081 // }1082 // and perform Verlet integration for each atom with position, velocity and force vector1083 runner = elemente->start;1084 while (runner->next != elemente->end) { // go through every element1085 runner = runner->next;1086 IonMass = runner->mass;1087 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1088 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1089 AtomNo = 0;1090 walker = start;1091 while (walker->next != end) { // go through every atom of this element1092 walker = walker->next;1093 if (walker->type == runner) { // if this atom fits to element1094 // check size of vectors1095 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {1096 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;1097 Trajectories[walker].R.resize(MDSteps+10);1098 Trajectories[walker].U.resize(MDSteps+10);1099 Trajectories[walker].F.resize(MDSteps+10);1100 }1101 // 1. calculate x(t+\delta t)1102 for (int d=0; d<NDIM; d++) {1103 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];1104 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];1105 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);1106 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 * t1107 }1108 // 2. Calculate v(t+\delta t)1109 for (int d=0; d<NDIM; d++) {1110 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];1111 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;1112 }1113 // cout << "Integrated position&velocity of step " << (MDSteps) << ": (";1114 // for (int d=0;d<NDIM;d++)1115 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1116 // cout << ")\t(";1117 // for (int d=0;d<NDIM;d++)1118 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1119 // cout << ")" << endl;1120 // next atom1121 AtomNo++;1122 }1123 }1124 }1125 }1126 }1127 // // correct velocities (rather momenta) so that center of mass remains motionless1128 // tmpvector.zero()1129 // IonMass = 0.;1130 // walker = start;1131 // while (walker->next != end) { // go through every atom1132 // walker = walker->next;1133 // IonMass += walker->type->mass;// sum up total mass1134 // for(int d=0;d<NDIM;d++) {1135 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;1136 // }1137 // }1138 // walker = start;1139 // while (walker->next != end) { // go through every atom of this element1140 // walker = walker->next;1141 // for(int d=0;d<NDIM;d++) {1142 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;1143 // }1144 // }1145 MDSteps++;1146 1147 1148 // exit1149 return true;1046 element *runner = elemente->start; 1047 atom *walker = NULL; 1048 int AtomNo; 1049 ifstream input(file); 1050 string token; 1051 stringstream item; 1052 double a, IonMass; 1053 ForceMatrix Force; 1054 Vector tmpvector; 1055 1056 CountElements(); // make sure ElementsInMolecule is up to date 1057 1058 // check file 1059 if (input == NULL) { 1060 return false; 1061 } else { 1062 // parse file into ForceMatrix 1063 if (!Force.ParseMatrix(file, 0,0,0)) { 1064 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1065 return false; 1066 } 1067 if (Force.RowCounter[0] != AtomCount) { 1068 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1069 return false; 1070 } 1071 // correct Forces 1072 // for(int d=0;d<NDIM;d++) 1073 // tmpvector.x[d] = 0.; 1074 // for(int i=0;i<AtomCount;i++) 1075 // for(int d=0;d<NDIM;d++) { 1076 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1077 // } 1078 // for(int i=0;i<AtomCount;i++) 1079 // for(int d=0;d<NDIM;d++) { 1080 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1081 // } 1082 // and perform Verlet integration for each atom with position, velocity and force vector 1083 runner = elemente->start; 1084 while (runner->next != elemente->end) { // go through every element 1085 runner = runner->next; 1086 IonMass = runner->mass; 1087 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1088 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1089 AtomNo = 0; 1090 walker = start; 1091 while (walker->next != end) { // go through every atom of this element 1092 walker = walker->next; 1093 if (walker->type == runner) { // if this atom fits to element 1094 // check size of vectors 1095 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1096 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1097 Trajectories[walker].R.resize(MDSteps+10); 1098 Trajectories[walker].U.resize(MDSteps+10); 1099 Trajectories[walker].F.resize(MDSteps+10); 1100 } 1101 // 1. calculate x(t+\delta t) 1102 for (int d=0; d<NDIM; d++) { 1103 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1104 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1105 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1106 Trajectories[walker].R.at(MDSteps).x[d] += 0.5*delta_t*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d])/IonMass; // F = m * a and s = 0.5 * F/m * t^2 = F * a * t 1107 } 1108 // 2. Calculate v(t+\delta t) 1109 for (int d=0; d<NDIM; d++) { 1110 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1111 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; 1112 } 1113 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1114 // for (int d=0;d<NDIM;d++) 1115 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1116 // cout << ")\t("; 1117 // for (int d=0;d<NDIM;d++) 1118 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1119 // cout << ")" << endl; 1120 // next atom 1121 AtomNo++; 1122 } 1123 } 1124 } 1125 } 1126 } 1127 // // correct velocities (rather momenta) so that center of mass remains motionless 1128 // tmpvector.zero() 1129 // IonMass = 0.; 1130 // walker = start; 1131 // while (walker->next != end) { // go through every atom 1132 // walker = walker->next; 1133 // IonMass += walker->type->mass; // sum up total mass 1134 // for(int d=0;d<NDIM;d++) { 1135 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1136 // } 1137 // } 1138 // walker = start; 1139 // while (walker->next != end) { // go through every atom of this element 1140 // walker = walker->next; 1141 // for(int d=0;d<NDIM;d++) { 1142 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1143 // } 1144 // } 1145 MDSteps++; 1146 1147 1148 // exit 1149 return true; 1150 1150 }; 1151 1151 … … 1155 1155 void molecule::Align(Vector *n) 1156 1156 { 1157 atom *ptr = start;1158 double alpha, tmp;1159 Vector z_axis;1160 z_axis.x[0] = 0.;1161 z_axis.x[1] = 0.;1162 z_axis.x[2] = 1.;1163 1164 // rotate on z-x plane1165 cout << Verbose(0) << "Begin of Aligning all atoms." << endl;1166 alpha = atan(-n->x[0]/n->x[2]);1167 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";1168 while (ptr->next != end) {1169 ptr = ptr->next;1170 tmp = ptr->x.x[0];1171 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1172 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1173 for (int j=0;j<MDSteps;j++) {1174 tmp = Trajectories[ptr].R.at(j).x[0];1175 Trajectories[ptr].R.at(j).x[0] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1176 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1177 }1178 }1179 // rotate n vector1180 tmp = n->x[0];1181 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1182 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1183 cout << Verbose(1) << "alignment vector after first rotation: ";1184 n->Output((ofstream *)&cout);1185 cout << endl;1186 1187 // rotate on z-y plane1188 ptr = start;1189 alpha = atan(-n->x[1]/n->x[2]);1190 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";1191 while (ptr->next != end) {1192 ptr = ptr->next;1193 tmp = ptr->x.x[1];1194 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1195 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1196 for (int j=0;j<MDSteps;j++) {1197 tmp = Trajectories[ptr].R.at(j).x[1];1198 Trajectories[ptr].R.at(j).x[1] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1199 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1200 }1201 }1202 // rotate n vector (for consistency check)1203 tmp = n->x[1];1204 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1205 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1206 1207 cout << Verbose(1) << "alignment vector after second rotation: ";1208 n->Output((ofstream *)&cout);1209 cout << Verbose(1) << endl;1210 cout << Verbose(0) << "End of Aligning all atoms." << endl;1157 atom *ptr = start; 1158 double alpha, tmp; 1159 Vector z_axis; 1160 z_axis.x[0] = 0.; 1161 z_axis.x[1] = 0.; 1162 z_axis.x[2] = 1.; 1163 1164 // rotate on z-x plane 1165 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1166 alpha = atan(-n->x[0]/n->x[2]); 1167 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1168 while (ptr->next != end) { 1169 ptr = ptr->next; 1170 tmp = ptr->x.x[0]; 1171 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1172 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1173 for (int j=0;j<MDSteps;j++) { 1174 tmp = Trajectories[ptr].R.at(j).x[0]; 1175 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1177 } 1178 } 1179 // rotate n vector 1180 tmp = n->x[0]; 1181 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1182 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1183 cout << Verbose(1) << "alignment vector after first rotation: "; 1184 n->Output((ofstream *)&cout); 1185 cout << endl; 1186 1187 // rotate on z-y plane 1188 ptr = start; 1189 alpha = atan(-n->x[1]/n->x[2]); 1190 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1191 while (ptr->next != end) { 1192 ptr = ptr->next; 1193 tmp = ptr->x.x[1]; 1194 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1195 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1196 for (int j=0;j<MDSteps;j++) { 1197 tmp = Trajectories[ptr].R.at(j).x[1]; 1198 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1199 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1200 } 1201 } 1202 // rotate n vector (for consistency check) 1203 tmp = n->x[1]; 1204 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1205 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1206 1207 cout << Verbose(1) << "alignment vector after second rotation: "; 1208 n->Output((ofstream *)&cout); 1209 cout << Verbose(1) << endl; 1210 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1211 1211 }; 1212 1212 … … 1217 1217 bool molecule::RemoveAtom(atom *pointer) 1218 1218 { 1219 if (ElementsInMolecule[pointer->type->Z] != 0)// this would indicate an error1220 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1221 else1222 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;1223 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1224 ElementCount--;1225 Trajectories.erase(pointer);1226 return remove(pointer, start, end);1219 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1220 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1221 else 1222 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1223 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1224 ElementCount--; 1225 Trajectories.erase(pointer); 1226 return remove(pointer, start, end); 1227 1227 }; 1228 1228 … … 1251 1251 bool molecule::CleanupMolecule() 1252 1252 { 1253 return (cleanup(start,end) && cleanup(first,last));1253 return (cleanup(start,end) && cleanup(first,last)); 1254 1254 }; 1255 1255 … … 1258 1258 * \return pointer to atom or NULL 1259 1259 */ 1260 atom * molecule::FindAtom(int Nr) const{1261 atom * walker = find(&Nr, start,end);1262 if (walker != NULL) {1263 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;1264 return walker;1265 } else {1266 cout << Verbose(0) << "Atom not found in list." << endl;1267 return NULL;1268 }1260 atom * molecule::FindAtom(int Nr) const{ 1261 atom * walker = find(&Nr, start,end); 1262 if (walker != NULL) { 1263 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1264 return walker; 1265 } else { 1266 cout << Verbose(0) << "Atom not found in list." << endl; 1267 return NULL; 1268 } 1269 1269 }; 1270 1270 … … 1274 1274 atom * molecule::AskAtom(string text) 1275 1275 { 1276 int No;1277 atom *ion = NULL;1278 do {1279 //cout << Verbose(0) << "============Atom list==========================" << endl;1280 //mol->Output((ofstream *)&cout);1281 //cout << Verbose(0) << "===============================================" << endl;1282 cout << Verbose(0) << text;1283 cin >> No;1284 ion = this->FindAtom(No);1285 } while (ion == NULL);1286 return ion;1276 int No; 1277 atom *ion = NULL; 1278 do { 1279 //cout << Verbose(0) << "============Atom list==========================" << endl; 1280 //mol->Output((ofstream *)&cout); 1281 //cout << Verbose(0) << "===============================================" << endl; 1282 cout << Verbose(0) << text; 1283 cin >> No; 1284 ion = this->FindAtom(No); 1285 } while (ion == NULL); 1286 return ion; 1287 1287 }; 1288 1288 … … 1293 1293 bool molecule::CheckBounds(const Vector *x) const 1294 1294 { 1295 bool result = true;1296 int j =-1;1297 for (int i=0;i<NDIM;i++) {1298 j += i+1;1299 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));1300 }1301 //return result;1302 return true; /// probably not gonna use the check no more1295 bool result = true; 1296 int j =-1; 1297 for (int i=0;i<NDIM;i++) { 1298 j += i+1; 1299 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1300 } 1301 //return result; 1302 return true; /// probably not gonna use the check no more 1303 1303 }; 1304 1304 … … 1310 1310 double LeastSquareDistance (const gsl_vector * x, void * params) 1311 1311 { 1312 double res = 0, t;1313 Vector a,b,c,d;1314 struct lsq_params *par = (struct lsq_params *)params;1315 atom *ptr = par->mol->start;1316 1317 // initialize vectors1318 a.x[0] = gsl_vector_get(x,0);1319 a.x[1] = gsl_vector_get(x,1);1320 a.x[2] = gsl_vector_get(x,2);1321 b.x[0] = gsl_vector_get(x,3);1322 b.x[1] = gsl_vector_get(x,4);1323 b.x[2] = gsl_vector_get(x,5);1324 // go through all atoms1325 while (ptr != par->mol->end) {1326 ptr = ptr->next;1327 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type1328 c.CopyVector(&ptr->x);// copy vector to temporary one1329 c.SubtractVector(&a);// subtract offset vector1330 t = c.ScalarProduct(&b);// get direction parameter1331 d.CopyVector(&b);// and create vector1332 d.Scale(&t);1333 c.SubtractVector(&d);// ... yielding distance vector1334 res += d.ScalarProduct((const Vector *)&d);// add squared distance1335 }1336 }1337 return res;1312 double res = 0, t; 1313 Vector a,b,c,d; 1314 struct lsq_params *par = (struct lsq_params *)params; 1315 atom *ptr = par->mol->start; 1316 1317 // initialize vectors 1318 a.x[0] = gsl_vector_get(x,0); 1319 a.x[1] = gsl_vector_get(x,1); 1320 a.x[2] = gsl_vector_get(x,2); 1321 b.x[0] = gsl_vector_get(x,3); 1322 b.x[1] = gsl_vector_get(x,4); 1323 b.x[2] = gsl_vector_get(x,5); 1324 // go through all atoms 1325 while (ptr != par->mol->end) { 1326 ptr = ptr->next; 1327 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1328 c.CopyVector(&ptr->x); // copy vector to temporary one 1329 c.SubtractVector(&a); // subtract offset vector 1330 t = c.ScalarProduct(&b); // get direction parameter 1331 d.CopyVector(&b); // and create vector 1332 d.Scale(&t); 1333 c.SubtractVector(&d); // ... yielding distance vector 1334 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1335 } 1336 } 1337 return res; 1338 1338 }; 1339 1339 … … 1343 1343 void molecule::GetAlignvector(struct lsq_params * par) const 1344 1344 { 1345 int np = 6;1346 1347 const gsl_multimin_fminimizer_type *T =1348 gsl_multimin_fminimizer_nmsimplex;1349 gsl_multimin_fminimizer *s = NULL;1350 gsl_vector *ss;1351 gsl_multimin_function minex_func;1352 1353 size_t iter = 0, i;1354 int status;1355 double size;1356 1357 /* Initial vertex size vector */1358 ss = gsl_vector_alloc (np);1359 1360 /* Set all step sizes to 1 */1361 gsl_vector_set_all (ss, 1.0);1362 1363 /* Starting point */1364 par->x = gsl_vector_alloc (np);1365 par->mol = this;1366 1367 gsl_vector_set (par->x, 0, 0.0);// offset1368 gsl_vector_set (par->x, 1, 0.0);1369 gsl_vector_set (par->x, 2, 0.0);1370 gsl_vector_set (par->x, 3, 0.0);// direction1371 gsl_vector_set (par->x, 4, 0.0);1372 gsl_vector_set (par->x, 5, 1.0);1373 1374 /* Initialize method and iterate */1375 minex_func.f = &LeastSquareDistance;1376 minex_func.n = np;1377 minex_func.params = (void *)par;1378 1379 s = gsl_multimin_fminimizer_alloc (T, np);1380 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);1381 1382 do1383 {1384 iter++;1385 status = gsl_multimin_fminimizer_iterate(s);1386 1387 if (status)1388 break;1389 1390 size = gsl_multimin_fminimizer_size (s);1391 status = gsl_multimin_test_size (size, 1e-2);1392 1393 if (status == GSL_SUCCESS)1394 {1395 printf ("converged to minimum at\n");1396 }1397 1398 printf ("%5d ", (int)iter);1399 for (i = 0; i < (size_t)np; i++)1400 {1401 printf ("%10.3e ", gsl_vector_get (s->x, i));1402 }1403 printf ("f() = %7.3f size = %.3f\n", s->fval, size);1404 }1405 while (status == GSL_CONTINUE && iter < 100);1406 1407 for (i=0;i<(size_t)np;i++)1408 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));1409 //gsl_vector_free(par->x);1410 gsl_vector_free(ss);1411 gsl_multimin_fminimizer_free (s);1345 int np = 6; 1346 1347 const gsl_multimin_fminimizer_type *T = 1348 gsl_multimin_fminimizer_nmsimplex; 1349 gsl_multimin_fminimizer *s = NULL; 1350 gsl_vector *ss; 1351 gsl_multimin_function minex_func; 1352 1353 size_t iter = 0, i; 1354 int status; 1355 double size; 1356 1357 /* Initial vertex size vector */ 1358 ss = gsl_vector_alloc (np); 1359 1360 /* Set all step sizes to 1 */ 1361 gsl_vector_set_all (ss, 1.0); 1362 1363 /* Starting point */ 1364 par->x = gsl_vector_alloc (np); 1365 par->mol = this; 1366 1367 gsl_vector_set (par->x, 0, 0.0); // offset 1368 gsl_vector_set (par->x, 1, 0.0); 1369 gsl_vector_set (par->x, 2, 0.0); 1370 gsl_vector_set (par->x, 3, 0.0); // direction 1371 gsl_vector_set (par->x, 4, 0.0); 1372 gsl_vector_set (par->x, 5, 1.0); 1373 1374 /* Initialize method and iterate */ 1375 minex_func.f = &LeastSquareDistance; 1376 minex_func.n = np; 1377 minex_func.params = (void *)par; 1378 1379 s = gsl_multimin_fminimizer_alloc (T, np); 1380 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1381 1382 do 1383 { 1384 iter++; 1385 status = gsl_multimin_fminimizer_iterate(s); 1386 1387 if (status) 1388 break; 1389 1390 size = gsl_multimin_fminimizer_size (s); 1391 status = gsl_multimin_test_size (size, 1e-2); 1392 1393 if (status == GSL_SUCCESS) 1394 { 1395 printf ("converged to minimum at\n"); 1396 } 1397 1398 printf ("%5d ", (int)iter); 1399 for (i = 0; i < (size_t)np; i++) 1400 { 1401 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1402 } 1403 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1404 } 1405 while (status == GSL_CONTINUE && iter < 100); 1406 1407 for (i=0;i<(size_t)np;i++) 1408 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1409 //gsl_vector_free(par->x); 1410 gsl_vector_free(ss); 1411 gsl_multimin_fminimizer_free (s); 1412 1412 }; 1413 1413 … … 1417 1417 bool molecule::Output(ofstream *out) 1418 1418 { 1419 element *runner;1420 atom *walker = NULL;1421 int ElementNo, AtomNo;1422 CountElements();1423 1424 if (out == NULL) {1425 return false;1426 } else {1427 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1428 ElementNo = 0;1429 runner = elemente->start;1430 while (runner->next != elemente->end) { // go through every element1431 runner = runner->next;1432 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1433 ElementNo++;1434 AtomNo = 0;1435 walker = start;1436 while (walker->next != end) { // go through every atom of this element1437 walker = walker->next;1438 if (walker->type == runner) { // if this atom fits to element1439 AtomNo++;1440 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories1441 }1442 }1443 }1444 }1445 return true;1446 }1419 element *runner; 1420 atom *walker = NULL; 1421 int ElementNo, AtomNo; 1422 CountElements(); 1423 1424 if (out == NULL) { 1425 return false; 1426 } else { 1427 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1428 ElementNo = 0; 1429 runner = elemente->start; 1430 while (runner->next != elemente->end) { // go through every element 1431 runner = runner->next; 1432 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1433 ElementNo++; 1434 AtomNo = 0; 1435 walker = start; 1436 while (walker->next != end) { // go through every atom of this element 1437 walker = walker->next; 1438 if (walker->type == runner) { // if this atom fits to element 1439 AtomNo++; 1440 walker->Output(ElementNo, AtomNo, out); // removed due to trajectories 1441 } 1442 } 1443 } 1444 } 1445 return true; 1446 } 1447 1447 }; 1448 1448 … … 1452 1452 bool molecule::OutputTrajectories(ofstream *out) 1453 1453 { 1454 element *runner = NULL;1455 atom *walker = NULL;1456 int ElementNo, AtomNo;1457 CountElements();1458 1459 if (out == NULL) {1460 return false;1461 } else {1462 for (int step = 0; step < MDSteps; step++) {1463 if (step == 0) {1464 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1465 } else {1466 *out << "# ====== MD step " << step << " =========" << endl;1467 }1468 ElementNo = 0;1469 runner = elemente->start;1470 while (runner->next != elemente->end) { // go through every element1471 runner = runner->next;1472 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1473 ElementNo++;1474 AtomNo = 0;1475 walker = start;1476 while (walker->next != end) { // go through every atom of this element1477 walker = walker->next;1478 if (walker->type == runner) { // if this atom fits to element1479 AtomNo++;1480 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t"<< fixed << setprecision(9) << showpoint;1481 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2];1482 *out << "\t" << walker->FixedIon;1483 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON)1484 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t";1485 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON)1486 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t";1487 *out << "\t# Number in molecule " << walker->nr << endl;1488 }1489 }1490 }1491 }1492 }1493 return true;1494 }1454 element *runner = NULL; 1455 atom *walker = NULL; 1456 int ElementNo, AtomNo; 1457 CountElements(); 1458 1459 if (out == NULL) { 1460 return false; 1461 } else { 1462 for (int step = 0; step < MDSteps; step++) { 1463 if (step == 0) { 1464 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1465 } else { 1466 *out << "# ====== MD step " << step << " =========" << endl; 1467 } 1468 ElementNo = 0; 1469 runner = elemente->start; 1470 while (runner->next != elemente->end) { // go through every element 1471 runner = runner->next; 1472 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1473 ElementNo++; 1474 AtomNo = 0; 1475 walker = start; 1476 while (walker->next != end) { // go through every atom of this element 1477 walker = walker->next; 1478 if (walker->type == runner) { // if this atom fits to element 1479 AtomNo++; 1480 *out << "Ion_Type" << ElementNo << "_" << AtomNo << "\t" << fixed << setprecision(9) << showpoint; 1481 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1482 *out << "\t" << walker->FixedIon; 1483 if (Trajectories[walker].U.at(step).Norm() > MYEPSILON) 1484 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].U.at(step).x[0] << "\t" << Trajectories[walker].U.at(step).x[1] << "\t" << Trajectories[walker].U.at(step).x[2] << "\t"; 1485 if (Trajectories[walker].F.at(step).Norm() > MYEPSILON) 1486 *out << "\t" << scientific << setprecision(6) << Trajectories[walker].F.at(step).x[0] << "\t" << Trajectories[walker].F.at(step).x[1] << "\t" << Trajectories[walker].F.at(step).x[2] << "\t"; 1487 *out << "\t# Number in molecule " << walker->nr << endl; 1488 } 1489 } 1490 } 1491 } 1492 } 1493 return true; 1494 } 1495 1495 }; 1496 1496 … … 1500 1500 void molecule::OutputListOfBonds(ofstream *out) const 1501 1501 { 1502 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;1503 atom *Walker = start;1504 while (Walker->next != end) {1505 Walker = Walker->next;1502 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1503 atom *Walker = start; 1504 while (Walker->next != end) { 1505 Walker = Walker->next; 1506 1506 #ifdef ADDHYDROGEN 1507 if (Walker->type->Z != 1) {// regard only non-hydrogen1507 if (Walker->type->Z != 1) { // regard only non-hydrogen 1508 1508 #endif 1509 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;1510 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {1511 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;1512 }1509 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1510 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1511 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1512 } 1513 1513 #ifdef ADDHYDROGEN 1514 }1514 } 1515 1515 #endif 1516 }1517 *out << endl;1516 } 1517 *out << endl; 1518 1518 }; 1519 1519 … … 1521 1521 * \param *out stream pointer 1522 1522 */ 1523 bool molecule::Checkout(ofstream *out) const1524 { 1525 return elemente->Checkout(out, ElementsInMolecule);1523 bool molecule::Checkout(ofstream *out) const 1524 { 1525 return elemente->Checkout(out, ElementsInMolecule); 1526 1526 }; 1527 1527 … … 1531 1531 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1532 1532 { 1533 atom *walker = NULL;1534 int No = 0;1535 time_t now;1536 1537 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1538 walker = start;1539 while (walker->next != end) { // go through every atom and count1540 walker = walker->next;1541 No++;1542 }1543 if (out != NULL) {1544 for (int step=0;step<MDSteps;step++) {1545 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);1546 walker = start;1547 while (walker->next != end) { // go through every atom of this element1548 walker = walker->next;1549 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl;1550 }1551 }1552 return true;1553 } else1554 return false;1533 atom *walker = NULL; 1534 int No = 0; 1535 time_t now; 1536 1537 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1538 walker = start; 1539 while (walker->next != end) { // go through every atom and count 1540 walker = walker->next; 1541 No++; 1542 } 1543 if (out != NULL) { 1544 for (int step=0;step<MDSteps;step++) { 1545 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1546 walker = start; 1547 while (walker->next != end) { // go through every atom of this element 1548 walker = walker->next; 1549 *out << walker->type->symbol << "\t" << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2] << endl; 1550 } 1551 } 1552 return true; 1553 } else 1554 return false; 1555 1555 }; 1556 1556 … … 1560 1560 bool molecule::OutputXYZ(ofstream *out) const 1561 1561 { 1562 atom *walker = NULL;1563 int AtomNo = 0, ElementNo;1564 time_t now;1565 element *runner = NULL;1566 1567 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1568 walker = start;1569 while (walker->next != end) { // go through every atom and count1570 walker = walker->next;1571 AtomNo++;1572 }1573 if (out != NULL) {1574 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);1575 ElementNo = 0;1576 runner = elemente->start;1577 while (runner->next != elemente->end) { // go through every element1578 runner = runner->next;1579 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1580 ElementNo++;1581 walker = start;1582 while (walker->next != end) { // go through every atom of this element1583 walker = walker->next;1584 if (walker->type == runner) { // if this atom fits to element1585 walker->OutputXYZLine(out);1586 }1587 }1588 }1589 }1590 return true;1591 } else1592 return false;1562 atom *walker = NULL; 1563 int AtomNo = 0, ElementNo; 1564 time_t now; 1565 element *runner = NULL; 1566 1567 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1568 walker = start; 1569 while (walker->next != end) { // go through every atom and count 1570 walker = walker->next; 1571 AtomNo++; 1572 } 1573 if (out != NULL) { 1574 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1575 ElementNo = 0; 1576 runner = elemente->start; 1577 while (runner->next != elemente->end) { // go through every element 1578 runner = runner->next; 1579 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1580 ElementNo++; 1581 walker = start; 1582 while (walker->next != end) { // go through every atom of this element 1583 walker = walker->next; 1584 if (walker->type == runner) { // if this atom fits to element 1585 walker->OutputXYZLine(out); 1586 } 1587 } 1588 } 1589 } 1590 return true; 1591 } else 1592 return false; 1593 1593 }; 1594 1594 … … 1598 1598 void molecule::CountAtoms(ofstream *out) 1599 1599 { 1600 int i = 0;1601 atom *Walker = start;1602 while (Walker->next != end) {1603 Walker = Walker->next;1604 i++;1605 }1606 if ((AtomCount == 0) || (i != AtomCount)) {1607 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;1608 AtomCount = i;1609 1610 // count NonHydrogen atoms and give each atom a unique name1611 if (AtomCount != 0) {1612 i=0;1613 NoNonHydrogen = 0;1614 Walker = start;1615 while (Walker->next != end) {1616 Walker = Walker->next;1617 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1618 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it1619 NoNonHydrogen++;1620 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");1621 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");1622 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);1623 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;1624 i++;1625 }1626 } else1627 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;1628 }1600 int i = 0; 1601 atom *Walker = start; 1602 while (Walker->next != end) { 1603 Walker = Walker->next; 1604 i++; 1605 } 1606 if ((AtomCount == 0) || (i != AtomCount)) { 1607 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1608 AtomCount = i; 1609 1610 // count NonHydrogen atoms and give each atom a unique name 1611 if (AtomCount != 0) { 1612 i=0; 1613 NoNonHydrogen = 0; 1614 Walker = start; 1615 while (Walker->next != end) { 1616 Walker = Walker->next; 1617 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1618 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1619 NoNonHydrogen++; 1620 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1621 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1622 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1623 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1624 i++; 1625 } 1626 } else 1627 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1628 } 1629 1629 }; 1630 1630 … … 1633 1633 void molecule::CountElements() 1634 1634 { 1635 int i = 0;1636 for(i=MAX_ELEMENTS;i--;)1637 ElementsInMolecule[i] = 0;1638 ElementCount = 0;1639 1640 atom *walker = start;1641 while (walker->next != end) {1642 walker = walker->next;1643 ElementsInMolecule[walker->type->Z]++;1644 i++;1645 }1646 for(i=MAX_ELEMENTS;i--;)1647 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);1635 int i = 0; 1636 for(i=MAX_ELEMENTS;i--;) 1637 ElementsInMolecule[i] = 0; 1638 ElementCount = 0; 1639 1640 atom *walker = start; 1641 while (walker->next != end) { 1642 walker = walker->next; 1643 ElementsInMolecule[walker->type->Z]++; 1644 i++; 1645 } 1646 for(i=MAX_ELEMENTS;i--;) 1647 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1648 1648 }; 1649 1649 … … 1655 1655 int molecule::CountCyclicBonds(ofstream *out) 1656 1656 { 1657 int No = 0;1658 int *MinimumRingSize = NULL;1659 MoleculeLeafClass *Subgraphs = NULL;1660 class StackClass<bond *> *BackEdgeStack = NULL;1661 bond *Binder = first;1662 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {1663 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;1664 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);1665 while (Subgraphs->next != NULL) {1666 Subgraphs = Subgraphs->next;1667 delete(Subgraphs->previous);1668 }1669 delete(Subgraphs);1670 delete[](MinimumRingSize);1671 }1672 while(Binder->next != last) {1673 Binder = Binder->next;1674 if (Binder->Cyclic)1675 No++;1676 }1677 delete(BackEdgeStack);1678 return No;1657 int No = 0; 1658 int *MinimumRingSize = NULL; 1659 MoleculeLeafClass *Subgraphs = NULL; 1660 class StackClass<bond *> *BackEdgeStack = NULL; 1661 bond *Binder = first; 1662 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1663 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1664 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1665 while (Subgraphs->next != NULL) { 1666 Subgraphs = Subgraphs->next; 1667 delete(Subgraphs->previous); 1668 } 1669 delete(Subgraphs); 1670 delete[](MinimumRingSize); 1671 } 1672 while(Binder->next != last) { 1673 Binder = Binder->next; 1674 if (Binder->Cyclic) 1675 No++; 1676 } 1677 delete(BackEdgeStack); 1678 return No; 1679 1679 }; 1680 1680 /** Returns Shading as a char string. … … 1684 1684 string molecule::GetColor(enum Shading color) 1685 1685 { 1686 switch(color) {1687 case white:1688 return "white";1689 break;1690 case lightgray:1691 return "lightgray";1692 break;1693 case darkgray:1694 return "darkgray";1695 break;1696 case black:1697 return "black";1698 break;1699 default:1700 return "uncolored";1701 break;1702 };1686 switch(color) { 1687 case white: 1688 return "white"; 1689 break; 1690 case lightgray: 1691 return "lightgray"; 1692 break; 1693 case darkgray: 1694 return "darkgray"; 1695 break; 1696 case black: 1697 return "black"; 1698 break; 1699 default: 1700 return "uncolored"; 1701 break; 1702 }; 1703 1703 }; 1704 1704 … … 1709 1709 void molecule::CalculateOrbitals(class config &configuration) 1710 1710 { 1711 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;1712 for(int i=MAX_ELEMENTS;i--;) {1713 if (ElementsInMolecule[i] != 0) {1714 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;1715 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);1716 }1717 }1718 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);1719 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;1720 configuration.MaxPsiDouble /= 2;1721 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;1722 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {1723 configuration.ProcPEGamma /= 2;1724 configuration.ProcPEPsi *= 2;1725 } else {1726 configuration.ProcPEGamma *= configuration.ProcPEPsi;1727 configuration.ProcPEPsi = 1;1728 }1729 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;1711 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1712 for(int i=MAX_ELEMENTS;i--;) { 1713 if (ElementsInMolecule[i] != 0) { 1714 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1715 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1716 } 1717 } 1718 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1719 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1720 configuration.MaxPsiDouble /= 2; 1721 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1722 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1723 configuration.ProcPEGamma /= 2; 1724 configuration.ProcPEPsi *= 2; 1725 } else { 1726 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1727 configuration.ProcPEPsi = 1; 1728 } 1729 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1730 1730 }; 1731 1731 … … 1736 1736 { 1737 1737 1738 // 1 We will parse bonds out of the dbond file created by tremolo.1739 int atom1, atom2, temp;1740 atom *Walker, *OtherWalker;1741 1742 if (!input)1743 {1744 cout << Verbose(1) << "Opening silica failed \n";1745 };1746 1747 *input >> ws >> atom1;1748 *input >> ws >> atom2;1749 cout << Verbose(1) << "Scanning file\n";1750 while (!input->eof()) // Check whether we read everything already1751 {1752 *input >> ws >> atom1;1753 *input >> ws >> atom2;1754 if(atom2<atom1) //Sort indices of atoms in order1755 {1756 temp=atom1;1757 atom1=atom2;1758 atom2=temp;1759 };1760 1761 Walker=start;1762 while(Walker-> nr != atom1) // Find atom corresponding to first index1763 {1764 Walker = Walker->next;1765 };1766 OtherWalker = Walker->next;1767 while(OtherWalker->nr != atom2) // Find atom corresponding to second index1768 {1769 OtherWalker= OtherWalker->next;1770 };1771 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.1772 1773 }1774 1775 CreateListOfBondsPerAtom(out);1738 // 1 We will parse bonds out of the dbond file created by tremolo. 1739 int atom1, atom2, temp; 1740 atom *Walker, *OtherWalker; 1741 1742 if (!input) 1743 { 1744 cout << Verbose(1) << "Opening silica failed \n"; 1745 }; 1746 1747 *input >> ws >> atom1; 1748 *input >> ws >> atom2; 1749 cout << Verbose(1) << "Scanning file\n"; 1750 while (!input->eof()) // Check whether we read everything already 1751 { 1752 *input >> ws >> atom1; 1753 *input >> ws >> atom2; 1754 if(atom2<atom1) //Sort indices of atoms in order 1755 { 1756 temp=atom1; 1757 atom1=atom2; 1758 atom2=temp; 1759 }; 1760 1761 Walker=start; 1762 while(Walker-> nr != atom1) // Find atom corresponding to first index 1763 { 1764 Walker = Walker->next; 1765 }; 1766 OtherWalker = Walker->next; 1767 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1768 { 1769 OtherWalker= OtherWalker->next; 1770 }; 1771 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1772 1773 } 1774 1775 CreateListOfBondsPerAtom(out); 1776 1776 1777 1777 }; … … 1784 1784 * To make it O(N log N) the function uses the linked-cell technique as follows: 1785 1785 * The procedure is step-wise: 1786 * -# Remove every bond in list1787 * -# Count the atoms in the molecule with CountAtoms()1788 * -# partition cell into smaller linked cells of size \a bonddistance1789 * -# put each atom into its corresponding cell1790 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true1791 * -# create the list of bonds via CreateListOfBondsPerAtom()1792 * -# correct the bond degree iteratively (single->double->triple bond)1793 * -# finally print the bond list to \a *out if desired1786 * -# Remove every bond in list 1787 * -# Count the atoms in the molecule with CountAtoms() 1788 * -# partition cell into smaller linked cells of size \a bonddistance 1789 * -# put each atom into its corresponding cell 1790 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1791 * -# create the list of bonds via CreateListOfBondsPerAtom() 1792 * -# correct the bond degree iteratively (single->double->triple bond) 1793 * -# finally print the bond list to \a *out if desired 1794 1794 * \param *out out stream for printing the matrix, NULL if no output 1795 1795 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1799 1799 { 1800 1800 1801 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;1802 int No, NoBonds, CandidateBondNo;1803 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;1804 molecule **CellList;1805 double distance, MinDistance, MaxDistance;1806 double *matrix = ReturnFullMatrixforSymmetric(cell_size);1807 Vector x;1808 int FalseBondDegree = 0;1809 1810 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);1811 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;1812 // remove every bond from the list1813 if ((first->next != last) && (last->previous != first)) {// there are bonds present1814 cleanup(first,last);1815 }1816 1817 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)1818 CountAtoms(out);1819 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;1820 1821 if (AtomCount != 0) {1822 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell1823 j=-1;1824 for (int i=0;i<NDIM;i++) {1825 j += i+1;1826 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance1827 //*out << Verbose(1) << "divisor[" << i << "]= " << divisor[i] << "." << endl;1828 }1829 // 2a. allocate memory for the cell list1830 NumberCells = divisor[0]*divisor[1]*divisor[2];1831 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;1832 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");1833 for (int i=NumberCells;i--;)1834 CellList[i] = NULL;1835 1836 // 2b. put all atoms into its corresponding list1837 Walker = start;1838 while(Walker->next != end) {1839 Walker = Walker->next;1840 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";1841 //Walker->x.Output(out);1842 //*out << "." << endl;1843 // compute the cell by the atom's coordinates1844 j=-1;1845 for (int i=0;i<NDIM;i++) {1846 j += i+1;1847 x.CopyVector(&(Walker->x));1848 x.KeepPeriodic(out, matrix);1849 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);1850 }1851 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];1852 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;1853 // add copy atom to this cell1854 if (CellList[index] == NULL)// allocate molecule if not done1855 CellList[index] = new molecule(elemente);1856 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference1857 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;1858 }1859 //for (int i=0;i<NumberCells;i++)1860 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;1861 1862 1863 // 3a. go through every cell1864 for (N[0]=divisor[0];N[0]--;)1865 for (N[1]=divisor[1];N[1]--;)1866 for (N[2]=divisor[2];N[2]--;) {1867 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];1868 if (CellList[Index] != NULL) { // if there atoms in this cell1869 //*out << Verbose(1) << "Current cell is " << Index << "." << endl;1870 // 3b. for every atom therein1871 Walker = CellList[Index]->start;1872 while (Walker->next != CellList[Index]->end) {// go through every atom1873 Walker = Walker->next;1874 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;1875 // 3c. check for possible bond between each atom in this and every one in the 27 cells1876 for (n[0]=-1;n[0]<=1;n[0]++)1877 for (n[1]=-1;n[1]<=1;n[1]++)1878 for (n[2]=-1;n[2]<=1;n[2]++) {1879 // compute the index of this comparison cell and make it periodic1880 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2];1881 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;1882 if (CellList[index] != NULL) {// if there are any atoms in this cell1883 OtherWalker = CellList[index]->start;1884 while(OtherWalker->next != CellList[index]->end) {// go through every atom in this cell1885 OtherWalker = OtherWalker->next;1886 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;1887 /// \todo periodic check is missing here!1888 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;1889 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;1890 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;1891 MaxDistance = MinDistance + BONDTHRESHOLD;1892 MinDistance -= BONDTHRESHOLD;1893 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);1894 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller1895 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;1896 AddBond(Walker->father, OtherWalker->father, 1);// also increases molecule::BondCount1897 } else {1898 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;1899 }1900 }1901 }1902 }1903 }1904 }1905 }1906 1907 1908 1909 // 4. free the cell again1910 for (int i=NumberCells;i--;)1911 if (CellList[i] != NULL) {1912 delete(CellList[i]);1913 }1914 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");1915 1916 // create the adjacency list per atom1917 CreateListOfBondsPerAtom(out);1918 1919 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,1920 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene1921 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of1922 // double bonds as was expected.1923 if (BondCount != 0) {1924 NoCyclicBonds = 0;1925 *out << Verbose(1) << "Correcting Bond degree of each bond ... ";1926 do {1927 No = 0; // No acts as breakup flag (if 1 we still continue)1928 Walker = start;1929 while (Walker->next != end) { // go through every atom1930 Walker = Walker->next;1931 // count valence of first partner1932 NoBonds = 0;1933 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)1934 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;1935 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1936 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch1937 Candidate = NULL;1938 CandidateBondNo = -1;1939 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners1940 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);1941 // count valence of second partner1942 NoBonds = 0;1943 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)1944 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;1945 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1946 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate1947 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first1948 Candidate = OtherWalker;1949 CandidateBondNo = i;1950 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;1951 }1952 }1953 }1954 if ((Candidate != NULL) && (CandidateBondNo != -1)) {1955 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;1956 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;1957 } else1958 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;1959 FalseBondDegree++;1960 }1961 }1962 } while (No);1963 *out << " done." << endl;1964 } else1965 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;1966 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;1967 1968 // output bonds for debugging (if bond chain list was correctly installed)1969 *out << Verbose(1) << endl << "From contents of bond chain list:";1970 bond *Binder = first;1971 while(Binder->next != last) {1972 Binder = Binder->next;1973 *out << *Binder << "\t" << endl;1974 }1975 *out << endl;1976 } else1977 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;1978 *out << Verbose(0) << "End of CreateAdjacencyList." << endl;1979 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");1801 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1802 int No, NoBonds, CandidateBondNo; 1803 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1804 molecule **CellList; 1805 double distance, MinDistance, MaxDistance; 1806 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1807 Vector x; 1808 int FalseBondDegree = 0; 1809 1810 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1811 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1812 // remove every bond from the list 1813 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1814 cleanup(first,last); 1815 } 1816 1817 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1818 CountAtoms(out); 1819 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1820 1821 if (AtomCount != 0) { 1822 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1823 j=-1; 1824 for (int i=0;i<NDIM;i++) { 1825 j += i+1; 1826 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1827 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1828 } 1829 // 2a. allocate memory for the cell list 1830 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1831 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1832 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1833 for (int i=NumberCells;i--;) 1834 CellList[i] = NULL; 1835 1836 // 2b. put all atoms into its corresponding list 1837 Walker = start; 1838 while(Walker->next != end) { 1839 Walker = Walker->next; 1840 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1841 //Walker->x.Output(out); 1842 //*out << "." << endl; 1843 // compute the cell by the atom's coordinates 1844 j=-1; 1845 for (int i=0;i<NDIM;i++) { 1846 j += i+1; 1847 x.CopyVector(&(Walker->x)); 1848 x.KeepPeriodic(out, matrix); 1849 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1850 } 1851 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1852 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1853 // add copy atom to this cell 1854 if (CellList[index] == NULL) // allocate molecule if not done 1855 CellList[index] = new molecule(elemente); 1856 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1857 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1858 } 1859 //for (int i=0;i<NumberCells;i++) 1860 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1861 1862 1863 // 3a. go through every cell 1864 for (N[0]=divisor[0];N[0]--;) 1865 for (N[1]=divisor[1];N[1]--;) 1866 for (N[2]=divisor[2];N[2]--;) { 1867 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1868 if (CellList[Index] != NULL) { // if there atoms in this cell 1869 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1870 // 3b. for every atom therein 1871 Walker = CellList[Index]->start; 1872 while (Walker->next != CellList[Index]->end) { // go through every atom 1873 Walker = Walker->next; 1874 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1875 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1876 for (n[0]=-1;n[0]<=1;n[0]++) 1877 for (n[1]=-1;n[1]<=1;n[1]++) 1878 for (n[2]=-1;n[2]<=1;n[2]++) { 1879 // compute the index of this comparison cell and make it periodic 1880 index = ((N[2]+n[2]+divisor[2])%divisor[2]) + (((N[1]+n[1]+divisor[1])%divisor[1]) + ((N[0]+n[0]+divisor[0])%divisor[0]) * divisor[1]) * divisor[2]; 1881 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1882 if (CellList[index] != NULL) { // if there are any atoms in this cell 1883 OtherWalker = CellList[index]->start; 1884 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1885 OtherWalker = OtherWalker->next; 1886 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1887 /// \todo periodic check is missing here! 1888 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1889 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1890 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1891 MaxDistance = MinDistance + BONDTHRESHOLD; 1892 MinDistance -= BONDTHRESHOLD; 1893 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1894 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1895 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1896 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1897 } else { 1898 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1899 } 1900 } 1901 } 1902 } 1903 } 1904 } 1905 } 1906 1907 1908 1909 // 4. free the cell again 1910 for (int i=NumberCells;i--;) 1911 if (CellList[i] != NULL) { 1912 delete(CellList[i]); 1913 } 1914 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1915 1916 // create the adjacency list per atom 1917 CreateListOfBondsPerAtom(out); 1918 1919 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1920 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1921 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1922 // double bonds as was expected. 1923 if (BondCount != 0) { 1924 NoCyclicBonds = 0; 1925 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1926 do { 1927 No = 0; // No acts as breakup flag (if 1 we still continue) 1928 Walker = start; 1929 while (Walker->next != end) { // go through every atom 1930 Walker = Walker->next; 1931 // count valence of first partner 1932 NoBonds = 0; 1933 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1934 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1935 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1936 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1937 Candidate = NULL; 1938 CandidateBondNo = -1; 1939 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1940 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1941 // count valence of second partner 1942 NoBonds = 0; 1943 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1944 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1945 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1946 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1947 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1948 Candidate = OtherWalker; 1949 CandidateBondNo = i; 1950 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1951 } 1952 } 1953 } 1954 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1955 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1956 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 1957 } else 1958 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 1959 FalseBondDegree++; 1960 } 1961 } 1962 } while (No); 1963 *out << " done." << endl; 1964 } else 1965 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1966 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1967 1968 // output bonds for debugging (if bond chain list was correctly installed) 1969 *out << Verbose(1) << endl << "From contents of bond chain list:"; 1970 bond *Binder = first; 1971 while(Binder->next != last) { 1972 Binder = Binder->next; 1973 *out << *Binder << "\t" << endl; 1974 } 1975 *out << endl; 1976 } else 1977 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1978 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1979 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1980 1980 1981 1981 }; … … 1993 1993 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 1994 1994 { 1995 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);1996 BackEdgeStack = new StackClass<bond *> (BondCount);1997 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);1998 MoleculeLeafClass *LeafWalker = SubGraphs;1999 int CurrentGraphNr = 0, OldGraphNr;2000 int ComponentNumber = 0;2001 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;2002 bond *Binder = NULL;2003 bool BackStepping = false;2004 2005 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;2006 2007 ResetAllBondsToUnused();2008 ResetAllAtomNumbers();2009 InitComponentNumbers();2010 BackEdgeStack->ClearStack();2011 while (Root != end) { // if there any atoms at all2012 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all2013 AtomStack->ClearStack();2014 2015 // put into new subgraph molecule and add this to list of subgraphs2016 LeafWalker = new MoleculeLeafClass(LeafWalker);2017 LeafWalker->Leaf = new molecule(elemente);2018 LeafWalker->Leaf->AddCopyAtom(Root);2019 2020 OldGraphNr = CurrentGraphNr;2021 Walker = Root;2022 do { // (10)2023 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom2024 if (!BackStepping) { // if we don't just return from (8)2025 Walker->GraphNr = CurrentGraphNr;2026 Walker->LowpointNr = CurrentGraphNr;2027 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;2028 AtomStack->Push(Walker);2029 CurrentGraphNr++;2030 }2031 do { // (3) if Walker has no unused egdes, go to (5)2032 BackStepping = false; // reset backstepping flag for (8)2033 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused2034 Binder = FindNextUnused(Walker);2035 if (Binder == NULL)2036 break;2037 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;2038 // (4) Mark Binder used, ...2039 Binder->MarkUsed(black);2040 OtherAtom = Binder->GetOtherAtom(Walker);2041 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;2042 if (OtherAtom->GraphNr != -1) {2043 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)2044 Binder->Type = BackEdge;2045 BackEdgeStack->Push(Binder);2046 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;2047 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;2048 } else {2049 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)2050 Binder->Type = TreeEdge;2051 OtherAtom->Ancestor = Walker;2052 Walker = OtherAtom;2053 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;2054 break;2055 }2056 Binder = NULL;2057 } while (1);// (3)2058 if (Binder == NULL) {2059 *out << Verbose(2) << "No more Unused Bonds." << endl;2060 break;2061 } else2062 Binder = NULL;2063 } while (1);// (2)2064 2065 // 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!2066 if ((Walker == Root) && (Binder == NULL))2067 break;2068 2069 // (5) if Ancestor of Walker is ...2070 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;2071 if (Walker->Ancestor->GraphNr != Root->GraphNr) {2072 // (6)(Ancestor of Walker is not Root)2073 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {2074 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)2075 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;2076 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;2077 } else {2078 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component2079 Walker->Ancestor->SeparationVertex = true;2080 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;2081 SetNextComponentNumber(Walker->Ancestor, ComponentNumber);2082 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;2083 SetNextComponentNumber(Walker, ComponentNumber);2084 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;2085 do {2086 OtherAtom = AtomStack->PopLast();2087 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2088 SetNextComponentNumber(OtherAtom, ComponentNumber);2089 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2090 } while (OtherAtom != Walker);2091 ComponentNumber++;2092 }2093 // (8) Walker becomes its Ancestor, go to (3)2094 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;2095 Walker = Walker->Ancestor;2096 BackStepping = true;2097 }2098 if (!BackStepping) {// coming from (8) want to go to (3)2099 // (9) remove all from stack till Walker (including), these and Root form a component2100 AtomStack->Output(out);2101 SetNextComponentNumber(Root, ComponentNumber);2102 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;2103 SetNextComponentNumber(Walker, ComponentNumber);2104 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;2105 do {2106 OtherAtom = AtomStack->PopLast();2107 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2108 SetNextComponentNumber(OtherAtom, ComponentNumber);2109 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2110 } while (OtherAtom != Walker);2111 ComponentNumber++;2112 2113 // (11) Root is separation vertex,set Walker to Root and go to (4)2114 Walker = Root;2115 Binder = FindNextUnused(Walker);2116 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;2117 if (Binder != NULL) { // Root is separation vertex2118 *out << Verbose(1) << "(11) Root is a separation vertex." << endl;2119 Walker->SeparationVertex = true;2120 }2121 }2122 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges2123 2124 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph2125 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;2126 LeafWalker->Leaf->Output(out);2127 *out << endl;2128 2129 // step on to next root2130 while ((Root != end) && (Root->GraphNr != -1)) {2131 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;2132 if (Root->GraphNr != -1) // if already discovered, step on2133 Root = Root->next;2134 }2135 }2136 // set cyclic bond criterium on "same LP" basis2137 Binder = first;2138 while(Binder->next != last) {2139 Binder = Binder->next;2140 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??2141 Binder->Cyclic = true;2142 NoCyclicBonds++;2143 }2144 }2145 2146 2147 *out << Verbose(1) << "Final graph info for each atom is:" << endl;2148 Walker = start;2149 while (Walker->next != end) {2150 Walker = Walker->next;2151 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";2152 OutputComponentNumber(out, Walker);2153 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;2154 }2155 2156 *out << Verbose(1) << "Final graph info for each bond is:" << endl;2157 Binder = first;2158 while(Binder->next != last) {2159 Binder = Binder->next;2160 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";2161 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";2162 OutputComponentNumber(out, Binder->leftatom);2163 *out << " ===";2164 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";2165 OutputComponentNumber(out, Binder->rightatom);2166 *out << ">." << endl;2167 if (Binder->Cyclic) // cyclic ??2168 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;2169 }2170 2171 // free all and exit2172 delete(AtomStack);2173 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;2174 return SubGraphs;1995 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 1996 BackEdgeStack = new StackClass<bond *> (BondCount); 1997 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 1998 MoleculeLeafClass *LeafWalker = SubGraphs; 1999 int CurrentGraphNr = 0, OldGraphNr; 2000 int ComponentNumber = 0; 2001 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 2002 bond *Binder = NULL; 2003 bool BackStepping = false; 2004 2005 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2006 2007 ResetAllBondsToUnused(); 2008 ResetAllAtomNumbers(); 2009 InitComponentNumbers(); 2010 BackEdgeStack->ClearStack(); 2011 while (Root != end) { // if there any atoms at all 2012 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 2013 AtomStack->ClearStack(); 2014 2015 // put into new subgraph molecule and add this to list of subgraphs 2016 LeafWalker = new MoleculeLeafClass(LeafWalker); 2017 LeafWalker->Leaf = new molecule(elemente); 2018 LeafWalker->Leaf->AddCopyAtom(Root); 2019 2020 OldGraphNr = CurrentGraphNr; 2021 Walker = Root; 2022 do { // (10) 2023 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 2024 if (!BackStepping) { // if we don't just return from (8) 2025 Walker->GraphNr = CurrentGraphNr; 2026 Walker->LowpointNr = CurrentGraphNr; 2027 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 2028 AtomStack->Push(Walker); 2029 CurrentGraphNr++; 2030 } 2031 do { // (3) if Walker has no unused egdes, go to (5) 2032 BackStepping = false; // reset backstepping flag for (8) 2033 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 2034 Binder = FindNextUnused(Walker); 2035 if (Binder == NULL) 2036 break; 2037 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 2038 // (4) Mark Binder used, ... 2039 Binder->MarkUsed(black); 2040 OtherAtom = Binder->GetOtherAtom(Walker); 2041 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 2042 if (OtherAtom->GraphNr != -1) { 2043 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2044 Binder->Type = BackEdge; 2045 BackEdgeStack->Push(Binder); 2046 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2047 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2048 } else { 2049 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2050 Binder->Type = TreeEdge; 2051 OtherAtom->Ancestor = Walker; 2052 Walker = OtherAtom; 2053 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2054 break; 2055 } 2056 Binder = NULL; 2057 } while (1); // (3) 2058 if (Binder == NULL) { 2059 *out << Verbose(2) << "No more Unused Bonds." << endl; 2060 break; 2061 } else 2062 Binder = NULL; 2063 } while (1); // (2) 2064 2065 // 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! 2066 if ((Walker == Root) && (Binder == NULL)) 2067 break; 2068 2069 // (5) if Ancestor of Walker is ... 2070 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2071 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2072 // (6) (Ancestor of Walker is not Root) 2073 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2074 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2075 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2076 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2077 } else { 2078 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2079 Walker->Ancestor->SeparationVertex = true; 2080 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2081 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2082 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2083 SetNextComponentNumber(Walker, ComponentNumber); 2084 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2085 do { 2086 OtherAtom = AtomStack->PopLast(); 2087 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2088 SetNextComponentNumber(OtherAtom, ComponentNumber); 2089 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2090 } while (OtherAtom != Walker); 2091 ComponentNumber++; 2092 } 2093 // (8) Walker becomes its Ancestor, go to (3) 2094 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2095 Walker = Walker->Ancestor; 2096 BackStepping = true; 2097 } 2098 if (!BackStepping) { // coming from (8) want to go to (3) 2099 // (9) remove all from stack till Walker (including), these and Root form a component 2100 AtomStack->Output(out); 2101 SetNextComponentNumber(Root, ComponentNumber); 2102 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2103 SetNextComponentNumber(Walker, ComponentNumber); 2104 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2105 do { 2106 OtherAtom = AtomStack->PopLast(); 2107 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2108 SetNextComponentNumber(OtherAtom, ComponentNumber); 2109 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2110 } while (OtherAtom != Walker); 2111 ComponentNumber++; 2112 2113 // (11) Root is separation vertex, set Walker to Root and go to (4) 2114 Walker = Root; 2115 Binder = FindNextUnused(Walker); 2116 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2117 if (Binder != NULL) { // Root is separation vertex 2118 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2119 Walker->SeparationVertex = true; 2120 } 2121 } 2122 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2123 2124 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2125 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2126 LeafWalker->Leaf->Output(out); 2127 *out << endl; 2128 2129 // step on to next root 2130 while ((Root != end) && (Root->GraphNr != -1)) { 2131 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2132 if (Root->GraphNr != -1) // if already discovered, step on 2133 Root = Root->next; 2134 } 2135 } 2136 // set cyclic bond criterium on "same LP" basis 2137 Binder = first; 2138 while(Binder->next != last) { 2139 Binder = Binder->next; 2140 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2141 Binder->Cyclic = true; 2142 NoCyclicBonds++; 2143 } 2144 } 2145 2146 2147 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2148 Walker = start; 2149 while (Walker->next != end) { 2150 Walker = Walker->next; 2151 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2152 OutputComponentNumber(out, Walker); 2153 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2154 } 2155 2156 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2157 Binder = first; 2158 while(Binder->next != last) { 2159 Binder = Binder->next; 2160 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2161 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2162 OutputComponentNumber(out, Binder->leftatom); 2163 *out << " === "; 2164 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2165 OutputComponentNumber(out, Binder->rightatom); 2166 *out << ">." << endl; 2167 if (Binder->Cyclic) // cyclic ?? 2168 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2169 } 2170 2171 // free all and exit 2172 delete(AtomStack); 2173 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2174 return SubGraphs; 2175 2175 }; 2176 2176 … … 2185 2185 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2186 2186 */ 2187 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize)2188 { 2189 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");2190 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");2191 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");2192 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2193 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2194 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;2195 bond *Binder = NULL, *BackEdge = NULL;2196 int RingSize, NumCycles, MinRingSize = -1;2197 2198 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray2199 for (int i=AtomCount;i--;) {2200 PredecessorList[i] = NULL;2201 ShortestPathList[i] = -1;2202 ColorList[i] = white;2203 }2204 2205 *out << Verbose(1) << "Back edge list - ";2206 BackEdgeStack->Output(out);2207 2208 *out << Verbose(1) << "Analysing cycles ... " << endl;2209 NumCycles = 0;2210 while (!BackEdgeStack->IsEmpty()) {2211 BackEdge = BackEdgeStack->PopFirst();2212 // this is the target2213 Root = BackEdge->leftatom;2214 // this is the source point2215 Walker = BackEdge->rightatom;2216 ShortestPathList[Walker->nr] = 0;2217 BFSStack->ClearStack();// start with empty BFS stack2218 BFSStack->Push(Walker);2219 TouchedStack->Push(Walker);2220 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2221 OtherAtom = NULL;2222 do {// look for Root2223 Walker = BFSStack->PopFirst();2224 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2225 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2226 Binder = ListOfBondsPerAtom[Walker->nr][i];2227 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)2228 OtherAtom = Binder->GetOtherAtom(Walker);2187 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2188 { 2189 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2190 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2191 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2192 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2193 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2194 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2195 bond *Binder = NULL, *BackEdge = NULL; 2196 int RingSize, NumCycles, MinRingSize = -1; 2197 2198 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2199 for (int i=AtomCount;i--;) { 2200 PredecessorList[i] = NULL; 2201 ShortestPathList[i] = -1; 2202 ColorList[i] = white; 2203 } 2204 2205 *out << Verbose(1) << "Back edge list - "; 2206 BackEdgeStack->Output(out); 2207 2208 *out << Verbose(1) << "Analysing cycles ... " << endl; 2209 NumCycles = 0; 2210 while (!BackEdgeStack->IsEmpty()) { 2211 BackEdge = BackEdgeStack->PopFirst(); 2212 // this is the target 2213 Root = BackEdge->leftatom; 2214 // this is the source point 2215 Walker = BackEdge->rightatom; 2216 ShortestPathList[Walker->nr] = 0; 2217 BFSStack->ClearStack(); // start with empty BFS stack 2218 BFSStack->Push(Walker); 2219 TouchedStack->Push(Walker); 2220 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2221 OtherAtom = NULL; 2222 do { // look for Root 2223 Walker = BFSStack->PopFirst(); 2224 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2225 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2226 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2227 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2228 OtherAtom = Binder->GetOtherAtom(Walker); 2229 2229 #ifdef ADDHYDROGEN 2230 if (OtherAtom->type->Z != 1) {2230 if (OtherAtom->type->Z != 1) { 2231 2231 #endif 2232 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2233 if (ColorList[OtherAtom->nr] == white) {2234 TouchedStack->Push(OtherAtom);2235 ColorList[OtherAtom->nr] = lightgray;2236 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2237 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2238 *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;2239 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance2240 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;2241 BFSStack->Push(OtherAtom);2242 //}2243 } else {2244 *out << Verbose(3) << "Not Adding, has already been visited." << endl;2245 }2246 if (OtherAtom == Root)2247 break;2232 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2233 if (ColorList[OtherAtom->nr] == white) { 2234 TouchedStack->Push(OtherAtom); 2235 ColorList[OtherAtom->nr] = lightgray; 2236 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2237 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2238 *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; 2239 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2240 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2241 BFSStack->Push(OtherAtom); 2242 //} 2243 } else { 2244 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2245 } 2246 if (OtherAtom == Root) 2247 break; 2248 2248 #ifdef ADDHYDROGEN 2249 } else {2250 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;2251 ColorList[OtherAtom->nr] = black;2252 }2249 } else { 2250 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2251 ColorList[OtherAtom->nr] = black; 2252 } 2253 2253 #endif 2254 } else {2255 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;2256 }2257 }2258 ColorList[Walker->nr] = black;2259 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2260 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand2261 // step through predecessor list2262 while (OtherAtom != BackEdge->rightatom) {2263 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2264 break;2265 else2266 OtherAtom = PredecessorList[OtherAtom->nr];2267 }2268 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already2269 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\2270 do {2271 OtherAtom = TouchedStack->PopLast();2272 if (PredecessorList[OtherAtom->nr] == Walker) {2273 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;2274 PredecessorList[OtherAtom->nr] = NULL;2275 ShortestPathList[OtherAtom->nr] = -1;2276 ColorList[OtherAtom->nr] = white;2277 BFSStack->RemoveItem(OtherAtom);2278 }2279 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));2280 TouchedStack->Push(OtherAtom);// last was wrongly popped2281 OtherAtom = BackEdge->rightatom; // set to not Root2282 } else2283 OtherAtom = Root;2284 }2285 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));2286 2287 if (OtherAtom == Root) {2288 // now climb back the predecessor list and thus find the cycle members2289 NumCycles++;2290 RingSize = 1;2291 Root->GetTrueFather()->IsCyclic = true;2292 *out << Verbose(1) << "Found ring contains: ";2293 Walker = Root;2294 while (Walker != BackEdge->rightatom) {2295 *out << Walker->Name << " <-> ";2296 Walker = PredecessorList[Walker->nr];2297 Walker->GetTrueFather()->IsCyclic = true;2298 RingSize++;2299 }2300 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2301 // walk through all and set MinimumRingSize2302 Walker = Root;2303 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2304 while (Walker != BackEdge->rightatom) {2305 Walker = PredecessorList[Walker->nr];2306 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])2307 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2308 }2309 if ((RingSize < MinRingSize) || (MinRingSize == -1))2310 MinRingSize = RingSize;2311 } else {2312 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;2313 }2314 2315 // now clean the lists2316 while (!TouchedStack->IsEmpty()){2317 Walker = TouchedStack->PopFirst();2318 PredecessorList[Walker->nr] = NULL;2319 ShortestPathList[Walker->nr] = -1;2320 ColorList[Walker->nr] = white;2321 }2322 }2323 if (MinRingSize != -1) {2324 // go over all atoms2325 Root = start;2326 while(Root->next != end) {2327 Root = Root->next;2328 2329 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is2330 Walker = Root;2331 ShortestPathList[Walker->nr] = 0;2332 BFSStack->ClearStack();// start with empty BFS stack2333 BFSStack->Push(Walker);2334 TouchedStack->Push(Walker);2335 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2336 OtherAtom = Walker;2337 while (OtherAtom != NULL) {// look for Root2338 Walker = BFSStack->PopFirst();2339 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2340 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2341 Binder = ListOfBondsPerAtom[Walker->nr][i];2342 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check2343 OtherAtom = Binder->GetOtherAtom(Walker);2344 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2345 if (ColorList[OtherAtom->nr] == white) {2346 TouchedStack->Push(OtherAtom);2347 ColorList[OtherAtom->nr] = lightgray;2348 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2349 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2350 //*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;2351 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring2352 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];2353 OtherAtom = NULL; //break;2354 break;2355 } else2356 BFSStack->Push(OtherAtom);2357 } else {2358 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;2359 }2360 } else {2361 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;2362 }2363 }2364 ColorList[Walker->nr] = black;2365 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2366 }2367 2368 // now clean the lists2369 while (!TouchedStack->IsEmpty()){2370 Walker = TouchedStack->PopFirst();2371 PredecessorList[Walker->nr] = NULL;2372 ShortestPathList[Walker->nr] = -1;2373 ColorList[Walker->nr] = white;2374 }2375 }2376 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;2377 }2378 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;2379 } else2380 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;2381 2382 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");2383 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");2384 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");2385 delete(BFSStack);2254 } else { 2255 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2256 } 2257 } 2258 ColorList[Walker->nr] = black; 2259 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2260 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2261 // step through predecessor list 2262 while (OtherAtom != BackEdge->rightatom) { 2263 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2264 break; 2265 else 2266 OtherAtom = PredecessorList[OtherAtom->nr]; 2267 } 2268 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2269 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2270 do { 2271 OtherAtom = TouchedStack->PopLast(); 2272 if (PredecessorList[OtherAtom->nr] == Walker) { 2273 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2274 PredecessorList[OtherAtom->nr] = NULL; 2275 ShortestPathList[OtherAtom->nr] = -1; 2276 ColorList[OtherAtom->nr] = white; 2277 BFSStack->RemoveItem(OtherAtom); 2278 } 2279 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2280 TouchedStack->Push(OtherAtom); // last was wrongly popped 2281 OtherAtom = BackEdge->rightatom; // set to not Root 2282 } else 2283 OtherAtom = Root; 2284 } 2285 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2286 2287 if (OtherAtom == Root) { 2288 // now climb back the predecessor list and thus find the cycle members 2289 NumCycles++; 2290 RingSize = 1; 2291 Root->GetTrueFather()->IsCyclic = true; 2292 *out << Verbose(1) << "Found ring contains: "; 2293 Walker = Root; 2294 while (Walker != BackEdge->rightatom) { 2295 *out << Walker->Name << " <-> "; 2296 Walker = PredecessorList[Walker->nr]; 2297 Walker->GetTrueFather()->IsCyclic = true; 2298 RingSize++; 2299 } 2300 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2301 // walk through all and set MinimumRingSize 2302 Walker = Root; 2303 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2304 while (Walker != BackEdge->rightatom) { 2305 Walker = PredecessorList[Walker->nr]; 2306 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2307 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2308 } 2309 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2310 MinRingSize = RingSize; 2311 } else { 2312 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2313 } 2314 2315 // now clean the lists 2316 while (!TouchedStack->IsEmpty()){ 2317 Walker = TouchedStack->PopFirst(); 2318 PredecessorList[Walker->nr] = NULL; 2319 ShortestPathList[Walker->nr] = -1; 2320 ColorList[Walker->nr] = white; 2321 } 2322 } 2323 if (MinRingSize != -1) { 2324 // go over all atoms 2325 Root = start; 2326 while(Root->next != end) { 2327 Root = Root->next; 2328 2329 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2330 Walker = Root; 2331 ShortestPathList[Walker->nr] = 0; 2332 BFSStack->ClearStack(); // start with empty BFS stack 2333 BFSStack->Push(Walker); 2334 TouchedStack->Push(Walker); 2335 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2336 OtherAtom = Walker; 2337 while (OtherAtom != NULL) { // look for Root 2338 Walker = BFSStack->PopFirst(); 2339 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2340 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2341 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2342 if ((Binder != BackEdge) || (NumberOfBondsPerAtom[Walker->nr] == 1)) { // only walk along DFS spanning tree (otherwise we always find SP of 1 being backedge Binder), but terminal hydrogens may be connected via backedge, hence extra check 2343 OtherAtom = Binder->GetOtherAtom(Walker); 2344 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2345 if (ColorList[OtherAtom->nr] == white) { 2346 TouchedStack->Push(OtherAtom); 2347 ColorList[OtherAtom->nr] = lightgray; 2348 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2349 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2350 //*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; 2351 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2352 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2353 OtherAtom = NULL; //break; 2354 break; 2355 } else 2356 BFSStack->Push(OtherAtom); 2357 } else { 2358 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2359 } 2360 } else { 2361 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2362 } 2363 } 2364 ColorList[Walker->nr] = black; 2365 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2366 } 2367 2368 // now clean the lists 2369 while (!TouchedStack->IsEmpty()){ 2370 Walker = TouchedStack->PopFirst(); 2371 PredecessorList[Walker->nr] = NULL; 2372 ShortestPathList[Walker->nr] = -1; 2373 ColorList[Walker->nr] = white; 2374 } 2375 } 2376 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2377 } 2378 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2379 } else 2380 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2381 2382 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2383 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2384 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2385 delete(BFSStack); 2386 2386 }; 2387 2387 … … 2393 2393 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2394 2394 { 2395 int i=0;2396 if (vertex != NULL) {2397 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {2398 if (vertex->ComponentNr[i] == -1) {// check if not yet used2399 vertex->ComponentNr[i] = nr;2400 break;2401 }2402 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time2403 break;// breaking here will not cause error!2404 }2405 if (i == NumberOfBondsPerAtom[vertex->nr])2406 cerr << "Error: All Component entries are already occupied!" << endl;2407 } else2408 cerr << "Error: Given vertex is NULL!" << endl;2395 int i=0; 2396 if (vertex != NULL) { 2397 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2398 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2399 vertex->ComponentNr[i] = nr; 2400 break; 2401 } 2402 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2403 break; // breaking here will not cause error! 2404 } 2405 if (i == NumberOfBondsPerAtom[vertex->nr]) 2406 cerr << "Error: All Component entries are already occupied!" << endl; 2407 } else 2408 cerr << "Error: Given vertex is NULL!" << endl; 2409 2409 }; 2410 2410 … … 2414 2414 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2415 2415 { 2416 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2417 *out << vertex->ComponentNr[i] << "";2416 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2417 *out << vertex->ComponentNr[i] << " "; 2418 2418 }; 2419 2419 … … 2422 2422 void molecule::InitComponentNumbers() 2423 2423 { 2424 atom *Walker = start;2425 while(Walker->next != end) {2426 Walker = Walker->next;2427 if (Walker->ComponentNr != NULL)2428 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");2429 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");2430 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)2431 Walker->ComponentNr[i] = -1;2432 }2424 atom *Walker = start; 2425 while(Walker->next != end) { 2426 Walker = Walker->next; 2427 if (Walker->ComponentNr != NULL) 2428 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2429 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2430 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2431 Walker->ComponentNr[i] = -1; 2432 } 2433 2433 }; 2434 2434 … … 2439 2439 bond * molecule::FindNextUnused(atom *vertex) 2440 2440 { 2441 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2442 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)2443 return(ListOfBondsPerAtom[vertex->nr][i]);2444 return NULL;2441 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2442 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2443 return(ListOfBondsPerAtom[vertex->nr][i]); 2444 return NULL; 2445 2445 }; 2446 2446 … … 2450 2450 void molecule::ResetAllBondsToUnused() 2451 2451 { 2452 bond *Binder = first;2453 while (Binder->next != last) {2454 Binder = Binder->next;2455 Binder->ResetUsed();2456 }2452 bond *Binder = first; 2453 while (Binder->next != last) { 2454 Binder = Binder->next; 2455 Binder->ResetUsed(); 2456 } 2457 2457 }; 2458 2458 … … 2461 2461 void molecule::ResetAllAtomNumbers() 2462 2462 { 2463 atom *Walker = start;2464 while (Walker->next != end) {2465 Walker = Walker->next;2466 Walker->GraphNr= -1;2467 }2463 atom *Walker = start; 2464 while (Walker->next != end) { 2465 Walker = Walker->next; 2466 Walker->GraphNr = -1; 2467 } 2468 2468 }; 2469 2469 … … 2474 2474 void OutputAlreadyVisited(ofstream *out, int *list) 2475 2475 { 2476 *out << Verbose(4) << "Already Visited Bonds:\t";2477 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2478 *out << endl;2476 *out << Verbose(4) << "Already Visited Bonds:\t"; 2477 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2478 *out << endl; 2479 2479 }; 2480 2480 … … 2482 2482 * The upper limit is 2483 2483 * \f[ 2484 * n = N \cdot C^k2484 * n = N \cdot C^k 2485 2485 * \f] 2486 2486 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2491 2491 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2492 2492 { 2493 int c = 0;2494 int FragmentCount;2495 // get maximum bond degree2496 atom *Walker = start;2497 while (Walker->next != end) {2498 Walker = Walker->next;2499 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;2500 }2501 FragmentCount = NoNonHydrogen*(1 << (c*order));2502 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;2503 return FragmentCount;2493 int c = 0; 2494 int FragmentCount; 2495 // get maximum bond degree 2496 atom *Walker = start; 2497 while (Walker->next != end) { 2498 Walker = Walker->next; 2499 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2500 } 2501 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2502 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2503 return FragmentCount; 2504 2504 }; 2505 2505 … … 2512 2512 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2513 2513 { 2514 stringstream line;2515 int AtomNr;2516 int status = 0;2517 2518 line.str(buffer);2519 while (!line.eof()) {2520 line >> AtomNr;2521 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2522 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2523 status++;2524 } // else it's "-1" or else and thus must not be added2525 }2526 *out << Verbose(1) << "The scanned KeySet is ";2527 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {2528 *out << (*runner) << "\t";2529 }2530 *out << endl;2531 return (status != 0);2514 stringstream line; 2515 int AtomNr; 2516 int status = 0; 2517 2518 line.str(buffer); 2519 while (!line.eof()) { 2520 line >> AtomNr; 2521 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2522 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2523 status++; 2524 } // else it's "-1" or else and thus must not be added 2525 } 2526 *out << Verbose(1) << "The scanned KeySet is "; 2527 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2528 *out << (*runner) << "\t"; 2529 } 2530 *out << endl; 2531 return (status != 0); 2532 2532 }; 2533 2533 … … 2544 2544 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2545 2545 { 2546 bool status = true;2547 ifstream InputFile;2548 stringstream line;2549 GraphTestPair testGraphInsert;2550 int NumberOfFragments = 0;2551 double TEFactor;2552 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");2553 2554 if (FragmentList == NULL) { // check list pointer2555 FragmentList = new Graph;2556 }2557 2558 // 1st pass: open file and read2559 *out << Verbose(1) << "Parsing the KeySet file ... " << endl;2560 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);2561 InputFile.open(filename);2562 if (InputFile != NULL) {2563 // each line represents a new fragment2564 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");2565 // 1. parse keysets and insert into temp. graph2566 while (!InputFile.eof()) {2567 InputFile.getline(buffer, MAXSTRINGSIZE);2568 KeySet CurrentSet;2569 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2570 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2571 if (!testGraphInsert.second) {2572 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;2573 }2574 }2575 }2576 // 2. Free and done2577 InputFile.close();2578 InputFile.clear();2579 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");2580 *out << Verbose(1) << "done." << endl;2581 } else {2582 *out << Verbose(1) << "File " << filename << " not found." << endl;2583 status = false;2584 }2585 2586 // 2nd pass: open TEFactors file and read2587 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;2588 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);2589 InputFile.open(filename);2590 if (InputFile != NULL) {2591 // 3. add found TEFactors to each keyset2592 NumberOfFragments = 0;2593 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {2594 if (!InputFile.eof()) {2595 InputFile >> TEFactor;2596 (*runner).second.second = TEFactor;2597 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;2598 } else {2599 status = false;2600 break;2601 }2602 }2603 // 4. Free and done2604 InputFile.close();2605 *out << Verbose(1) << "done." << endl;2606 } else {2607 *out << Verbose(1) << "File " << filename << " not found." << endl;2608 status = false;2609 }2610 2611 // free memory2612 Free((void **)&filename, "molecule::ParseKeySetFile - filename");2613 2614 return status;2546 bool status = true; 2547 ifstream InputFile; 2548 stringstream line; 2549 GraphTestPair testGraphInsert; 2550 int NumberOfFragments = 0; 2551 double TEFactor; 2552 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2553 2554 if (FragmentList == NULL) { // check list pointer 2555 FragmentList = new Graph; 2556 } 2557 2558 // 1st pass: open file and read 2559 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2560 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2561 InputFile.open(filename); 2562 if (InputFile != NULL) { 2563 // each line represents a new fragment 2564 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2565 // 1. parse keysets and insert into temp. graph 2566 while (!InputFile.eof()) { 2567 InputFile.getline(buffer, MAXSTRINGSIZE); 2568 KeySet CurrentSet; 2569 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2570 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2571 if (!testGraphInsert.second) { 2572 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2573 } 2574 } 2575 } 2576 // 2. Free and done 2577 InputFile.close(); 2578 InputFile.clear(); 2579 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2580 *out << Verbose(1) << "done." << endl; 2581 } else { 2582 *out << Verbose(1) << "File " << filename << " not found." << endl; 2583 status = false; 2584 } 2585 2586 // 2nd pass: open TEFactors file and read 2587 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2588 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2589 InputFile.open(filename); 2590 if (InputFile != NULL) { 2591 // 3. add found TEFactors to each keyset 2592 NumberOfFragments = 0; 2593 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2594 if (!InputFile.eof()) { 2595 InputFile >> TEFactor; 2596 (*runner).second.second = TEFactor; 2597 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2598 } else { 2599 status = false; 2600 break; 2601 } 2602 } 2603 // 4. Free and done 2604 InputFile.close(); 2605 *out << Verbose(1) << "done." << endl; 2606 } else { 2607 *out << Verbose(1) << "File " << filename << " not found." << endl; 2608 status = false; 2609 } 2610 2611 // free memory 2612 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2613 2614 return status; 2615 2615 }; 2616 2616 … … 2623 2623 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2624 2624 { 2625 ofstream output;2626 bool status =true;2627 string line;2628 2629 // open KeySet file2630 line = path;2631 line.append("/");2632 line += FRAGMENTPREFIX;2633 line += KEYSETFILE;2634 output.open(line.c_str(), ios::out);2635 *out << Verbose(1) << "Saving key sets of the total graph ... ";2636 if(output != NULL) {2637 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {2638 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {2639 if (sprinter != (*runner).first.begin())2640 output << "\t";2641 output << *sprinter;2642 }2643 output << endl;2644 }2645 *out << "done." << endl;2646 } else {2647 cerr << "Unable to open " << line << " for writing keysets!" << endl;2648 status = false;2649 }2650 output.close();2651 output.clear();2652 2653 // open TEFactors file2654 line = path;2655 line.append("/");2656 line += FRAGMENTPREFIX;2657 line += TEFACTORSFILE;2658 output.open(line.c_str(), ios::out);2659 *out << Verbose(1) << "Saving TEFactors of the total graph ... ";2660 if(output != NULL) {2661 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)2662 output << (*runner).second.second << endl;2663 *out << Verbose(1) << "done." << endl;2664 } else {2665 *out << Verbose(1) << "failed to open " << line << "." << endl;2666 status = false;2667 }2668 output.close();2669 2670 return status;2625 ofstream output; 2626 bool status = true; 2627 string line; 2628 2629 // open KeySet file 2630 line = path; 2631 line.append("/"); 2632 line += FRAGMENTPREFIX; 2633 line += KEYSETFILE; 2634 output.open(line.c_str(), ios::out); 2635 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2636 if(output != NULL) { 2637 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2638 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2639 if (sprinter != (*runner).first.begin()) 2640 output << "\t"; 2641 output << *sprinter; 2642 } 2643 output << endl; 2644 } 2645 *out << "done." << endl; 2646 } else { 2647 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2648 status = false; 2649 } 2650 output.close(); 2651 output.clear(); 2652 2653 // open TEFactors file 2654 line = path; 2655 line.append("/"); 2656 line += FRAGMENTPREFIX; 2657 line += TEFACTORSFILE; 2658 output.open(line.c_str(), ios::out); 2659 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2660 if(output != NULL) { 2661 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2662 output << (*runner).second.second << endl; 2663 *out << Verbose(1) << "done." << endl; 2664 } else { 2665 *out << Verbose(1) << "failed to open " << line << "." << endl; 2666 status = false; 2667 } 2668 output.close(); 2669 2670 return status; 2671 2671 }; 2672 2672 … … 2679 2679 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2680 2680 { 2681 ofstream AdjacencyFile;2682 atom *Walker = NULL;2683 stringstream line;2684 bool status = true;2685 2686 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2687 AdjacencyFile.open(line.str().c_str(), ios::out);2688 *out << Verbose(1) << "Saving adjacency list ... ";2689 if (AdjacencyFile != NULL) {2690 Walker = start;2691 while(Walker->next != end) {2692 Walker = Walker->next;2693 AdjacencyFile << Walker->nr << "\t";2694 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)2695 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";2696 AdjacencyFile << endl;2697 }2698 AdjacencyFile.close();2699 *out << Verbose(1) << "done." << endl;2700 } else {2701 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;2702 status = false;2703 }2704 2705 return status;2681 ofstream AdjacencyFile; 2682 atom *Walker = NULL; 2683 stringstream line; 2684 bool status = true; 2685 2686 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2687 AdjacencyFile.open(line.str().c_str(), ios::out); 2688 *out << Verbose(1) << "Saving adjacency list ... "; 2689 if (AdjacencyFile != NULL) { 2690 Walker = start; 2691 while(Walker->next != end) { 2692 Walker = Walker->next; 2693 AdjacencyFile << Walker->nr << "\t"; 2694 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2695 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2696 AdjacencyFile << endl; 2697 } 2698 AdjacencyFile.close(); 2699 *out << Verbose(1) << "done." << endl; 2700 } else { 2701 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2702 status = false; 2703 } 2704 2705 return status; 2706 2706 }; 2707 2707 … … 2714 2714 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2715 2715 { 2716 ifstream File;2717 stringstream filename;2718 bool status = true;2719 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2720 2721 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2722 File.open(filename.str().c_str(), ios::out);2723 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";2724 if (File != NULL) {2725 // allocate storage structure2726 int NonMatchNumber = 0;// will number of atoms with differing bond structure2727 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom2728 int CurrentBondsOfAtom;2729 2730 // Parse the file line by line and count the bonds2731 while (!File.eof()) {2732 File.getline(buffer, MAXSTRINGSIZE);2733 stringstream line;2734 line.str(buffer);2735 int AtomNr = -1;2736 line >> AtomNr;2737 CurrentBondsOfAtom = -1; // we count one too far due to line end2738 // parse into structure2739 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2740 while (!line.eof())2741 line >> CurrentBonds[ ++CurrentBondsOfAtom ];2742 // compare against present bonds2743 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";2744 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {2745 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {2746 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;2747 int j = 0;2748 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds2749 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms2750 ListOfAtoms[AtomNr] = NULL;2751 NonMatchNumber++;2752 status = false;2753 //out << "[" << id << "]\t";2754 } else {2755 //out << id << "\t";2756 }2757 }2758 //out << endl;2759 } else {2760 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;2761 status = false;2762 }2763 }2764 }2765 File.close();2766 File.clear();2767 if (status) { // if equal we parse the KeySetFile2768 *out << Verbose(1) << "done: Equal." << endl;2769 status = true;2770 } else2771 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;2772 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");2773 } else {2774 *out << Verbose(1) << "Adjacency file not found." << endl;2775 status = false;2776 }2777 *out << endl;2778 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2779 2780 return status;2716 ifstream File; 2717 stringstream filename; 2718 bool status = true; 2719 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2720 2721 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2722 File.open(filename.str().c_str(), ios::out); 2723 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2724 if (File != NULL) { 2725 // allocate storage structure 2726 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2727 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2728 int CurrentBondsOfAtom; 2729 2730 // Parse the file line by line and count the bonds 2731 while (!File.eof()) { 2732 File.getline(buffer, MAXSTRINGSIZE); 2733 stringstream line; 2734 line.str(buffer); 2735 int AtomNr = -1; 2736 line >> AtomNr; 2737 CurrentBondsOfAtom = -1; // we count one too far due to line end 2738 // parse into structure 2739 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2740 while (!line.eof()) 2741 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2742 // compare against present bonds 2743 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2744 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2745 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2746 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2747 int j = 0; 2748 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2749 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2750 ListOfAtoms[AtomNr] = NULL; 2751 NonMatchNumber++; 2752 status = false; 2753 //out << "[" << id << "]\t"; 2754 } else { 2755 //out << id << "\t"; 2756 } 2757 } 2758 //out << endl; 2759 } else { 2760 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2761 status = false; 2762 } 2763 } 2764 } 2765 File.close(); 2766 File.clear(); 2767 if (status) { // if equal we parse the KeySetFile 2768 *out << Verbose(1) << "done: Equal." << endl; 2769 status = true; 2770 } else 2771 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2772 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2773 } else { 2774 *out << Verbose(1) << "Adjacency file not found." << endl; 2775 status = false; 2776 } 2777 *out << endl; 2778 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2779 2780 return status; 2781 2781 }; 2782 2782 … … 2792 2792 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2793 2793 { 2794 atom *Walker = start;2795 bool status = false;2796 ifstream InputFile;2797 2798 // initialize mask list2799 for(int i=AtomCount;i--;)2800 AtomMask[i] = false;2801 2802 if (Order < 0) { // adaptive increase of BondOrder per site2803 if (AtomMask[AtomCount] == true)// break after one step2804 return false;2805 // parse the EnergyPerFragment file2806 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");2807 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);2808 InputFile.open(buffer, ios::in);2809 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {2810 // transmorph graph keyset list into indexed KeySetList2811 map<int,KeySet> IndexKeySetList;2812 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {2813 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );2814 }2815 int lines = 0;2816 // count the number of lines, i.e. the number of fragments2817 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2818 InputFile.getline(buffer, MAXSTRINGSIZE);2819 while(!InputFile.eof()) {2820 InputFile.getline(buffer, MAXSTRINGSIZE);2821 lines++;2822 }2823 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2824 InputFile.clear();2825 InputFile.seekg(ios::beg);2826 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2827 int No, FragOrder;2828 double Value;2829 // each line represents a fragment root (Atom::nr) id and its energy contribution2830 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2831 InputFile.getline(buffer, MAXSTRINGSIZE);2832 while(!InputFile.eof()) {2833 InputFile.getline(buffer, MAXSTRINGSIZE);2834 if (strlen(buffer) > 2) {2835 //*out << Verbose(2) << "Scanning: " << buffer << endl;2836 stringstream line(buffer);2837 line >> FragOrder;2838 line >> ws >> No;2839 line >> ws >> Value; // skip time entry2840 line >> ws >> Value;2841 No -= 1;// indices start at 1 in file, not 02842 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;2843 2844 // clean the list of those entries that have been superceded by higher order terms already2845 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2846 if (marker != IndexKeySetList.end()) {// if found2847 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2848 // 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 AtomMask2849 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));2850 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;2851 if (!InsertedElement.second) { // this root is already present2852 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2853 //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)2854 {// if value is smaller, update value and order2855 (*PresentItem).second.first = fabs(Value);2856 (*PresentItem).second.second = FragOrder;2857 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2858 } else {2859 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2860 }2861 } else {2862 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2863 }2864 } else {2865 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;2866 }2867 }2868 }2869 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)2870 map<double, pair<int,int> > FinalRootCandidates;2871 *out << Verbose(1) << "Root candidate list is: " << endl;2872 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {2873 Walker = FindAtom((*runner).first);2874 if (Walker != NULL) {2875 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order2876 if (!Walker->MaxOrder) {2877 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;2878 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );2879 } else {2880 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;2881 }2882 } else {2883 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;2884 }2885 }2886 // pick the ones still below threshold and mark as to be adaptively updated2887 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {2888 No = (*runner).second.first;2889 Walker = FindAtom(No);2890 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {2891 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;2892 AtomMask[No] = true;2893 status = true;2894 //} else2895 //*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;2896 }2897 // close and done2898 InputFile.close();2899 InputFile.clear();2900 } else {2901 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;2902 while (Walker->next != end) {2903 Walker = Walker->next;2904 #ifdef ADDHYDROGEN2905 if (Walker->type->Z != 1) // skip hydrogen2906 #endif2907 {2908 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2909 status = true;2910 }2911 }2912 }2913 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");2914 // pick a given number of highest values and set AtomMask2915 } else { // global increase of Bond Order2916 while (Walker->next != end) {2917 Walker = Walker->next;2918 #ifdef ADDHYDROGEN2919 if (Walker->type->Z != 1) // skip hydrogen2920 #endif2921 {2922 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2923 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))2924 status = true;2925 }2926 }2927 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2928 status = true;2929 2930 if (!status) {2931 if (Order == 0)2932 *out << Verbose(1) << "Single stepping done." << endl;2933 else2934 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;2935 }2936 }2937 2938 // print atom mask for debugging2939 *out << "";2940 for(int i=0;i<AtomCount;i++)2941 *out << (i % 10);2942 *out << endl << "Atom mask is: ";2943 for(int i=0;i<AtomCount;i++)2944 *out << (AtomMask[i] ? "t" : "f");2945 *out << endl;2946 2947 return status;2794 atom *Walker = start; 2795 bool status = false; 2796 ifstream InputFile; 2797 2798 // initialize mask list 2799 for(int i=AtomCount;i--;) 2800 AtomMask[i] = false; 2801 2802 if (Order < 0) { // adaptive increase of BondOrder per site 2803 if (AtomMask[AtomCount] == true) // break after one step 2804 return false; 2805 // parse the EnergyPerFragment file 2806 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2807 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2808 InputFile.open(buffer, ios::in); 2809 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2810 // transmorph graph keyset list into indexed KeySetList 2811 map<int,KeySet> IndexKeySetList; 2812 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2813 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2814 } 2815 int lines = 0; 2816 // count the number of lines, i.e. the number of fragments 2817 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2818 InputFile.getline(buffer, MAXSTRINGSIZE); 2819 while(!InputFile.eof()) { 2820 InputFile.getline(buffer, MAXSTRINGSIZE); 2821 lines++; 2822 } 2823 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2824 InputFile.clear(); 2825 InputFile.seekg(ios::beg); 2826 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2827 int No, FragOrder; 2828 double Value; 2829 // each line represents a fragment root (Atom::nr) id and its energy contribution 2830 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2831 InputFile.getline(buffer, MAXSTRINGSIZE); 2832 while(!InputFile.eof()) { 2833 InputFile.getline(buffer, MAXSTRINGSIZE); 2834 if (strlen(buffer) > 2) { 2835 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2836 stringstream line(buffer); 2837 line >> FragOrder; 2838 line >> ws >> No; 2839 line >> ws >> Value; // skip time entry 2840 line >> ws >> Value; 2841 No -= 1; // indices start at 1 in file, not 0 2842 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2843 2844 // clean the list of those entries that have been superceded by higher order terms already 2845 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2846 if (marker != IndexKeySetList.end()) { // if found 2847 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2848 // 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 2849 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2850 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2851 if (!InsertedElement.second) { // this root is already present 2852 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2853 //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) 2854 { // if value is smaller, update value and order 2855 (*PresentItem).second.first = fabs(Value); 2856 (*PresentItem).second.second = FragOrder; 2857 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2858 } else { 2859 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2860 } 2861 } else { 2862 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2863 } 2864 } else { 2865 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2866 } 2867 } 2868 } 2869 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2870 map<double, pair<int,int> > FinalRootCandidates; 2871 *out << Verbose(1) << "Root candidate list is: " << endl; 2872 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2873 Walker = FindAtom((*runner).first); 2874 if (Walker != NULL) { 2875 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2876 if (!Walker->MaxOrder) { 2877 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2878 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2879 } else { 2880 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2881 } 2882 } else { 2883 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2884 } 2885 } 2886 // pick the ones still below threshold and mark as to be adaptively updated 2887 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2888 No = (*runner).second.first; 2889 Walker = FindAtom(No); 2890 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2891 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2892 AtomMask[No] = true; 2893 status = true; 2894 //} else 2895 //*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; 2896 } 2897 // close and done 2898 InputFile.close(); 2899 InputFile.clear(); 2900 } else { 2901 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2902 while (Walker->next != end) { 2903 Walker = Walker->next; 2904 #ifdef ADDHYDROGEN 2905 if (Walker->type->Z != 1) // skip hydrogen 2906 #endif 2907 { 2908 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2909 status = true; 2910 } 2911 } 2912 } 2913 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2914 // pick a given number of highest values and set AtomMask 2915 } else { // global increase of Bond Order 2916 while (Walker->next != end) { 2917 Walker = Walker->next; 2918 #ifdef ADDHYDROGEN 2919 if (Walker->type->Z != 1) // skip hydrogen 2920 #endif 2921 { 2922 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2923 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2924 status = true; 2925 } 2926 } 2927 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2928 status = true; 2929 2930 if (!status) { 2931 if (Order == 0) 2932 *out << Verbose(1) << "Single stepping done." << endl; 2933 else 2934 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2935 } 2936 } 2937 2938 // print atom mask for debugging 2939 *out << " "; 2940 for(int i=0;i<AtomCount;i++) 2941 *out << (i % 10); 2942 *out << endl << "Atom mask is: "; 2943 for(int i=0;i<AtomCount;i++) 2944 *out << (AtomMask[i] ? "t" : "f"); 2945 *out << endl; 2946 2947 return status; 2948 2948 }; 2949 2949 … … 2955 2955 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2956 2956 { 2957 element *runner = elemente->start;2958 int AtomNo = 0;2959 atom *Walker = NULL;2960 2961 if (SortIndex != NULL) {2962 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;2963 return false;2964 }2965 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");2966 for(int i=AtomCount;i--;)2967 SortIndex[i] = -1;2968 while (runner->next != elemente->end) { // go through every element2969 runner = runner->next;2970 if (ElementsInMolecule[runner->Z]) { // if this element got atoms2971 Walker = start;2972 while (Walker->next != end) { // go through every atom of this element2973 Walker = Walker->next;2974 if (Walker->type->Z == runner->Z) // if this atom fits to element2975 SortIndex[Walker->nr] = AtomNo++;2976 }2977 }2978 }2979 return true;2957 element *runner = elemente->start; 2958 int AtomNo = 0; 2959 atom *Walker = NULL; 2960 2961 if (SortIndex != NULL) { 2962 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 2963 return false; 2964 } 2965 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 2966 for(int i=AtomCount;i--;) 2967 SortIndex[i] = -1; 2968 while (runner->next != elemente->end) { // go through every element 2969 runner = runner->next; 2970 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 2971 Walker = start; 2972 while (Walker->next != end) { // go through every atom of this element 2973 Walker = Walker->next; 2974 if (Walker->type->Z == runner->Z) // if this atom fits to element 2975 SortIndex[Walker->nr] = AtomNo++; 2976 } 2977 } 2978 } 2979 return true; 2980 2980 }; 2981 2981 … … 2986 2986 y contribution", and that's why this consciously not done in the following loop) 2987 2987 * -# in a loop over all subgraphs 2988 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure2989 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)2988 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 2989 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 2990 2990 * -# combines the generated molecule lists from all subgraphs 2991 2991 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 3000 3000 int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 3001 3001 { 3002 MoleculeListClass *BondFragments = NULL;3003 int *SortIndex = NULL;3004 int *MinimumRingSize = new int[AtomCount];3005 int FragmentCounter;3006 MoleculeLeafClass *MolecularWalker = NULL;3007 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis3008 fstream File;3009 bool FragmentationToDo = true;3010 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;3011 bool CheckOrder = false;3012 Graph **FragmentList = NULL;3013 Graph *ParsedFragmentList = NULL;3014 Graph TotalGraph;// graph with all keysets however local numbers3015 int TotalNumberOfKeySets = 0;3016 atom **ListOfAtoms = NULL;3017 atom ***ListOfLocalAtoms = NULL;3018 bool *AtomMask = NULL;3019 3020 *out << endl;3002 MoleculeListClass *BondFragments = NULL; 3003 int *SortIndex = NULL; 3004 int *MinimumRingSize = new int[AtomCount]; 3005 int FragmentCounter; 3006 MoleculeLeafClass *MolecularWalker = NULL; 3007 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 3008 fstream File; 3009 bool FragmentationToDo = true; 3010 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 3011 bool CheckOrder = false; 3012 Graph **FragmentList = NULL; 3013 Graph *ParsedFragmentList = NULL; 3014 Graph TotalGraph; // graph with all keysets however local numbers 3015 int TotalNumberOfKeySets = 0; 3016 atom **ListOfAtoms = NULL; 3017 atom ***ListOfLocalAtoms = NULL; 3018 bool *AtomMask = NULL; 3019 3020 *out << endl; 3021 3021 #ifdef ADDHYDROGEN 3022 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;3022 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 3023 3023 #else 3024 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;3024 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 3025 3025 #endif 3026 3026 3027 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++3028 3029 // ===== 1. Check whether bond structure is same as stored in files ====3030 3031 // fill the adjacency list3032 CreateListOfBondsPerAtom(out);3033 3034 // create lookup table for Atom::nr3035 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);3036 3037 // === compare it with adjacency file ===3038 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);3039 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");3040 3041 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====3042 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);3043 // fill the bond structure of the individually stored subgraphs3044 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3045 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph3046 for(int i=AtomCount;i--;)3047 MinimumRingSize[i] = AtomCount;3048 MolecularWalker = Subgraphs;3049 FragmentCounter = 0;3050 while (MolecularWalker->next != NULL) {3051 MolecularWalker = MolecularWalker->next;3052 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);3053 // // check the list of local atoms for debugging3054 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;3055 // for (int i=0;i<AtomCount;i++)3056 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL)3057 // *out << "\tNULL";3058 // else3059 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;3060 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3061 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);3062 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3063 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);3064 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3065 delete(LocalBackEdgeStack);3066 }3067 3068 // ===== 3. if structure still valid, parse key set file and others =====3069 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);3070 3071 // ===== 4. check globally whether there's something to do actually (first adaptivity check)3072 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);3073 3074 // =================================== Begin of FRAGMENTATION ===============================3075 // ===== 6a. assign each keyset to its respective subgraph =====3076 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);3077 3078 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle3079 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];3080 AtomMask = new bool[AtomCount+1];3081 AtomMask[AtomCount] = false;3082 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3083 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {3084 FragmentationToDo = FragmentationToDo || CheckOrder;3085 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3086 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====3087 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));3088 3089 // ===== 7. fill the bond fragment list =====3090 FragmentCounter = 0;3091 MolecularWalker = Subgraphs;3092 while (MolecularWalker->next != NULL) {3093 MolecularWalker = MolecularWalker->next;3094 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;3095 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3096 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {3097 // call BOSSANOVA method3098 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;3099 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);3100 } else {3101 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;3102 }3103 FragmentCounter++;// next fragment list3104 }3105 }3106 delete[](RootStack);3107 delete[](AtomMask);3108 delete(ParsedFragmentList);3109 delete[](MinimumRingSize);3110 3111 3112 // ==================================== End of FRAGMENTATION ============================================3113 3114 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)3115 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);3116 3117 // free subgraph memory again3118 FragmentCounter = 0;3119 if (Subgraphs != NULL) {3120 while (Subgraphs->next != NULL) {3121 Subgraphs = Subgraphs->next;3122 delete(FragmentList[FragmentCounter++]);3123 delete(Subgraphs->previous);3124 }3125 delete(Subgraphs);3126 }3127 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");3128 3129 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====3130 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3131 // allocate memory for the pointer array and transmorph graphs into full molecular fragments3132 BondFragments = new MoleculeListClass();3133 int k=0;3134 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {3135 KeySet test = (*runner).first;3136 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;3137 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));3138 k++;3139 }3140 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;3141 3142 // ===== 9. Save fragments' configuration and keyset files et al to disk ===3143 if (BondFragments->ListOfMolecules.size() != 0) {3144 // create the SortIndex from BFS labels to order in the config file3145 CreateMappingLabelsToConfigSequence(out, SortIndex);3146 3147 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;3148 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))3149 *out << Verbose(1) << "All configs written." << endl;3150 else3151 *out << Verbose(1) << "Some config writing failed." << endl;3152 3153 // store force index reference file3154 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);3155 3156 // store keysets file3157 StoreKeySetFile(out, TotalGraph, configuration->configpath);3158 3159 // store Adjacency file3160 StoreAdjacencyToFile(out, configuration->configpath);3161 3162 // store Hydrogen saturation correction file3163 BondFragments->AddHydrogenCorrection(out, configuration->configpath);3164 3165 // store adaptive orders into file3166 StoreOrderAtSiteFile(out, configuration->configpath);3167 3168 // restore orbital and Stop values3169 CalculateOrbitals(*configuration);3170 3171 // free memory for bond part3172 *out << Verbose(1) << "Freeing bond memory" << endl;3173 delete(FragmentList); // remove bond molecule from memory3174 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");3175 } else3176 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;3177 //} else3178 //*out << Verbose(1) << "No fragments to store." << endl;3179 *out << Verbose(0) << "End of bond fragmentation." << endl;3180 3181 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)3027 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3028 3029 // ===== 1. Check whether bond structure is same as stored in files ==== 3030 3031 // fill the adjacency list 3032 CreateListOfBondsPerAtom(out); 3033 3034 // create lookup table for Atom::nr 3035 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3036 3037 // === compare it with adjacency file === 3038 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3039 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3040 3041 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3042 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3043 // fill the bond structure of the individually stored subgraphs 3044 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3045 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3046 for(int i=AtomCount;i--;) 3047 MinimumRingSize[i] = AtomCount; 3048 MolecularWalker = Subgraphs; 3049 FragmentCounter = 0; 3050 while (MolecularWalker->next != NULL) { 3051 MolecularWalker = MolecularWalker->next; 3052 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3053 // // check the list of local atoms for debugging 3054 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3055 // for (int i=0;i<AtomCount;i++) 3056 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3057 // *out << "\tNULL"; 3058 // else 3059 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3060 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3061 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3062 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3063 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3064 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3065 delete(LocalBackEdgeStack); 3066 } 3067 3068 // ===== 3. if structure still valid, parse key set file and others ===== 3069 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3070 3071 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3072 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3073 3074 // =================================== Begin of FRAGMENTATION =============================== 3075 // ===== 6a. assign each keyset to its respective subgraph ===== 3076 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3077 3078 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3079 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3080 AtomMask = new bool[AtomCount+1]; 3081 AtomMask[AtomCount] = false; 3082 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3083 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3084 FragmentationToDo = FragmentationToDo || CheckOrder; 3085 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3086 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3087 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3088 3089 // ===== 7. fill the bond fragment list ===== 3090 FragmentCounter = 0; 3091 MolecularWalker = Subgraphs; 3092 while (MolecularWalker->next != NULL) { 3093 MolecularWalker = MolecularWalker->next; 3094 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3095 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3096 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3097 // call BOSSANOVA method 3098 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3099 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3100 } else { 3101 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3102 } 3103 FragmentCounter++; // next fragment list 3104 } 3105 } 3106 delete[](RootStack); 3107 delete[](AtomMask); 3108 delete(ParsedFragmentList); 3109 delete[](MinimumRingSize); 3110 3111 3112 // ==================================== End of FRAGMENTATION ============================================ 3113 3114 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3115 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3116 3117 // free subgraph memory again 3118 FragmentCounter = 0; 3119 if (Subgraphs != NULL) { 3120 while (Subgraphs->next != NULL) { 3121 Subgraphs = Subgraphs->next; 3122 delete(FragmentList[FragmentCounter++]); 3123 delete(Subgraphs->previous); 3124 } 3125 delete(Subgraphs); 3126 } 3127 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3128 3129 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3130 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3131 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3132 BondFragments = new MoleculeListClass(); 3133 int k=0; 3134 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3135 KeySet test = (*runner).first; 3136 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3137 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3138 k++; 3139 } 3140 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3141 3142 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3143 if (BondFragments->ListOfMolecules.size() != 0) { 3144 // create the SortIndex from BFS labels to order in the config file 3145 CreateMappingLabelsToConfigSequence(out, SortIndex); 3146 3147 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3148 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3149 *out << Verbose(1) << "All configs written." << endl; 3150 else 3151 *out << Verbose(1) << "Some config writing failed." << endl; 3152 3153 // store force index reference file 3154 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3155 3156 // store keysets file 3157 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3158 3159 // store Adjacency file 3160 StoreAdjacencyToFile(out, configuration->configpath); 3161 3162 // store Hydrogen saturation correction file 3163 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3164 3165 // store adaptive orders into file 3166 StoreOrderAtSiteFile(out, configuration->configpath); 3167 3168 // restore orbital and Stop values 3169 CalculateOrbitals(*configuration); 3170 3171 // free memory for bond part 3172 *out << Verbose(1) << "Freeing bond memory" << endl; 3173 delete(FragmentList); // remove bond molecule from memory 3174 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3175 } else 3176 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3177 //} else 3178 // *out << Verbose(1) << "No fragments to store." << endl; 3179 *out << Verbose(0) << "End of bond fragmentation." << endl; 3180 3181 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3182 3182 }; 3183 3183 … … 3192 3192 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3193 3193 { 3194 bool status = true;3195 if (ReferenceStack->IsEmpty()) {3196 cerr << "ReferenceStack is empty!" << endl;3197 return false;3198 }3199 bond *Binder = ReferenceStack->PopFirst();3200 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3201 atom *Walker = NULL, *OtherAtom = NULL;3202 ReferenceStack->Push(Binder);3203 3204 do {// go through all bonds and push local ones3205 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3206 if (Walker != NULL) // if this Walker exists in the subgraph ...3207 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3208 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3209 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3210 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3211 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;3212 break;3213 }3214 }3215 Binder = ReferenceStack->PopFirst();// loop the stack for next item3216 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;3217 ReferenceStack->Push(Binder);3218 } while (FirstBond != Binder);3219 3220 return status;3194 bool status = true; 3195 if (ReferenceStack->IsEmpty()) { 3196 cerr << "ReferenceStack is empty!" << endl; 3197 return false; 3198 } 3199 bond *Binder = ReferenceStack->PopFirst(); 3200 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3201 atom *Walker = NULL, *OtherAtom = NULL; 3202 ReferenceStack->Push(Binder); 3203 3204 do { // go through all bonds and push local ones 3205 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3206 if (Walker != NULL) // if this Walker exists in the subgraph ... 3207 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3208 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3209 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3210 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3211 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3212 break; 3213 } 3214 } 3215 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3216 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3217 ReferenceStack->Push(Binder); 3218 } while (FirstBond != Binder); 3219 3220 return status; 3221 3221 }; 3222 3222 … … 3229 3229 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3230 3230 { 3231 stringstream line;3232 ofstream file;3233 3234 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3235 file.open(line.str().c_str());3236 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;3237 if (file != NULL) {3238 atom *Walker = start;3239 while (Walker->next != end) {3240 Walker = Walker->next;3241 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;3242 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;3243 }3244 file.close();3245 *out << Verbose(1) << "done." << endl;3246 return true;3247 } else {3248 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3249 return false;3250 }3231 stringstream line; 3232 ofstream file; 3233 3234 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3235 file.open(line.str().c_str()); 3236 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3237 if (file != NULL) { 3238 atom *Walker = start; 3239 while (Walker->next != end) { 3240 Walker = Walker->next; 3241 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3242 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3243 } 3244 file.close(); 3245 *out << Verbose(1) << "done." << endl; 3246 return true; 3247 } else { 3248 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3249 return false; 3250 } 3251 3251 }; 3252 3252 … … 3260 3260 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3261 3261 { 3262 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3263 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3264 bool status;3265 int AtomNr, value;3266 stringstream line;3267 ifstream file;3268 3269 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;3270 for(int i=AtomCount;i--;)3271 OrderArray[i] = 0;3272 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3273 file.open(line.str().c_str());3274 if (file != NULL) {3275 for (int i=AtomCount;i--;) { // initialise with 03276 OrderArray[i] = 0;3277 MaxArray[i] = 0;3278 }3279 while (!file.eof()) { // parse from file3280 AtomNr = -1;3281 file >> AtomNr;3282 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)3283 file >> value;3284 OrderArray[AtomNr] = value;3285 file >> value;3286 MaxArray[AtomNr] = value;3287 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;3288 }3289 }3290 atom *Walker = start;3291 while (Walker->next != end) { // fill into atom classes3292 Walker = Walker->next;3293 Walker->AdaptiveOrder = OrderArray[Walker->nr];3294 Walker->MaxOrder = MaxArray[Walker->nr];3295 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;3296 }3297 file.close();3298 *out << Verbose(1) << "done." << endl;3299 status = true;3300 } else {3301 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3302 status = false;3303 }3304 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3305 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3306 3307 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;3308 return status;3262 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3263 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3264 bool status; 3265 int AtomNr, value; 3266 stringstream line; 3267 ifstream file; 3268 3269 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3270 for(int i=AtomCount;i--;) 3271 OrderArray[i] = 0; 3272 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3273 file.open(line.str().c_str()); 3274 if (file != NULL) { 3275 for (int i=AtomCount;i--;) { // initialise with 0 3276 OrderArray[i] = 0; 3277 MaxArray[i] = 0; 3278 } 3279 while (!file.eof()) { // parse from file 3280 AtomNr = -1; 3281 file >> AtomNr; 3282 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3283 file >> value; 3284 OrderArray[AtomNr] = value; 3285 file >> value; 3286 MaxArray[AtomNr] = value; 3287 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3288 } 3289 } 3290 atom *Walker = start; 3291 while (Walker->next != end) { // fill into atom classes 3292 Walker = Walker->next; 3293 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3294 Walker->MaxOrder = MaxArray[Walker->nr]; 3295 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3296 } 3297 file.close(); 3298 *out << Verbose(1) << "done." << endl; 3299 status = true; 3300 } else { 3301 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3302 status = false; 3303 } 3304 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3305 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3306 3307 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3308 return status; 3309 3309 }; 3310 3310 … … 3317 3317 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3318 3318 { 3319 bond *Binder = NULL;3320 atom *Walker = NULL;3321 int TotalDegree;3322 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;3323 3324 // re-allocate memory3325 *out << Verbose(2) << "(Re-)Allocating memory." << endl;3326 if (ListOfBondsPerAtom != NULL) {3327 for(int i=AtomCount;i--;)3328 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");3329 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");3330 }3331 if (NumberOfBondsPerAtom != NULL)3332 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");3333 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");3334 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");3335 3336 // reset bond counts per atom3337 for(int i=AtomCount;i--;)3338 NumberOfBondsPerAtom[i] = 0;3339 // count bonds per atom3340 Binder = first;3341 while (Binder->next != last) {3342 Binder = Binder->next;3343 NumberOfBondsPerAtom[Binder->leftatom->nr]++;3344 NumberOfBondsPerAtom[Binder->rightatom->nr]++;3345 }3346 for(int i=AtomCount;i--;) {3347 // allocate list of bonds per atom3348 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");3349 // clear the list again, now each NumberOfBondsPerAtom marks current free field3350 NumberOfBondsPerAtom[i] = 0;3351 }3352 // fill the list3353 Binder = first;3354 while (Binder->next != last) {3355 Binder = Binder->next;3356 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;3357 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;3358 }3359 3360 // output list for debugging3361 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;3362 Walker = start;3363 while (Walker->next != end) {3364 Walker = Walker->next;3365 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";3366 TotalDegree = 0;3367 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {3368 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";3369 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;3370 }3371 *out << " -- TotalDegree: " << TotalDegree << endl;3372 }3373 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;3319 bond *Binder = NULL; 3320 atom *Walker = NULL; 3321 int TotalDegree; 3322 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3323 3324 // re-allocate memory 3325 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3326 if (ListOfBondsPerAtom != NULL) { 3327 for(int i=AtomCount;i--;) 3328 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3329 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3330 } 3331 if (NumberOfBondsPerAtom != NULL) 3332 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3333 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3334 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3335 3336 // reset bond counts per atom 3337 for(int i=AtomCount;i--;) 3338 NumberOfBondsPerAtom[i] = 0; 3339 // count bonds per atom 3340 Binder = first; 3341 while (Binder->next != last) { 3342 Binder = Binder->next; 3343 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3344 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3345 } 3346 for(int i=AtomCount;i--;) { 3347 // allocate list of bonds per atom 3348 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3349 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3350 NumberOfBondsPerAtom[i] = 0; 3351 } 3352 // fill the list 3353 Binder = first; 3354 while (Binder->next != last) { 3355 Binder = Binder->next; 3356 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3357 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3358 } 3359 3360 // output list for debugging 3361 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3362 Walker = start; 3363 while (Walker->next != end) { 3364 Walker = Walker->next; 3365 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3366 TotalDegree = 0; 3367 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3368 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3369 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3370 } 3371 *out << " -- TotalDegree: " << TotalDegree << endl; 3372 } 3373 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3374 3374 }; 3375 3375 … … 3388 3388 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3389 3389 { 3390 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");3391 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");3392 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");3393 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);3394 atom *Walker = NULL, *OtherAtom = NULL;3395 bond *Binder = NULL;3396 3397 // add Root if not done yet3398 AtomStack->ClearStack();3399 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3400 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);3401 AtomStack->Push(Root);3402 3403 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray3404 for (int i=AtomCount;i--;) {3405 PredecessorList[i] = NULL;3406 ShortestPathList[i] = -1;3407 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited3408 ColorList[i] = lightgray;3409 else3410 ColorList[i] = white;3411 }3412 ShortestPathList[Root->nr] = 0;3413 3414 // and go on ... Queue always contains all lightgray vertices3415 while (!AtomStack->IsEmpty()) {3416 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.3417 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again3418 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and3419 // followed by n+1 till top of stack.3420 Walker = AtomStack->PopFirst(); // pop oldest added3421 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;3422 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {3423 Binder = ListOfBondsPerAtom[Walker->nr][i];3424 if (Binder != NULL) { // don't look at bond equal NULL3425 OtherAtom = Binder->GetOtherAtom(Walker);3426 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;3427 if (ColorList[OtherAtom->nr] == white) {3428 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)3429 ColorList[OtherAtom->nr] = lightgray;3430 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3431 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;3432 *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;3433 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance3434 *out << Verbose(3);3435 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far3436 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);3437 *out << "Added OtherAtom " << OtherAtom->Name;3438 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3439 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3440 AddedBondList[Binder->nr]->Type = Binder->Type;3441 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";3442 } else {// this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place)3443 *out << "Not adding OtherAtom " << OtherAtom->Name;3444 if (AddedBondList[Binder->nr] == NULL) {3445 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3446 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3447 AddedBondList[Binder->nr]->Type = Binder->Type;3448 *out << ", added Bond " << *(AddedBondList[Binder->nr]);3449 } else3450 *out << ", not added Bond ";3451 }3452 *out << ", putting OtherAtom into queue." << endl;3453 AtomStack->Push(OtherAtom);3454 } else { // out of bond order, then replace3455 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))3456 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)3457 if (Binder == Bond)3458 *out << Verbose(3) << "Not Queueing, is the Root bond";3459 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)3460 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;3461 if (!Binder->Cyclic)3462 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;3463 if (AddedBondList[Binder->nr] == NULL) {3464 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate3465 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3466 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3467 AddedBondList[Binder->nr]->Type = Binder->Type;3468 } else {3390 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3391 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3392 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3393 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3394 atom *Walker = NULL, *OtherAtom = NULL; 3395 bond *Binder = NULL; 3396 3397 // add Root if not done yet 3398 AtomStack->ClearStack(); 3399 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3400 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3401 AtomStack->Push(Root); 3402 3403 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3404 for (int i=AtomCount;i--;) { 3405 PredecessorList[i] = NULL; 3406 ShortestPathList[i] = -1; 3407 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3408 ColorList[i] = lightgray; 3409 else 3410 ColorList[i] = white; 3411 } 3412 ShortestPathList[Root->nr] = 0; 3413 3414 // and go on ... Queue always contains all lightgray vertices 3415 while (!AtomStack->IsEmpty()) { 3416 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3417 // e.g. if current atom is 2, push to end of stack are of length 3, but first all of length 2 would be popped. They again 3418 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3419 // followed by n+1 till top of stack. 3420 Walker = AtomStack->PopFirst(); // pop oldest added 3421 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3422 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3423 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3424 if (Binder != NULL) { // don't look at bond equal NULL 3425 OtherAtom = Binder->GetOtherAtom(Walker); 3426 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3427 if (ColorList[OtherAtom->nr] == white) { 3428 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) 3429 ColorList[OtherAtom->nr] = lightgray; 3430 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3431 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3432 *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; 3433 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3434 *out << Verbose(3); 3435 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3436 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3437 *out << "Added OtherAtom " << OtherAtom->Name; 3438 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3439 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3440 AddedBondList[Binder->nr]->Type = Binder->Type; 3441 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3442 } else { // this code should actually never come into play (all white atoms are not yet present in BondMolecule, that's why they are white in the first place) 3443 *out << "Not adding OtherAtom " << OtherAtom->Name; 3444 if (AddedBondList[Binder->nr] == NULL) { 3445 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3446 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3447 AddedBondList[Binder->nr]->Type = Binder->Type; 3448 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3449 } else 3450 *out << ", not added Bond "; 3451 } 3452 *out << ", putting OtherAtom into queue." << endl; 3453 AtomStack->Push(OtherAtom); 3454 } else { // out of bond order, then replace 3455 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3456 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3457 if (Binder == Bond) 3458 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3459 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3460 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3461 if (!Binder->Cyclic) 3462 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3463 if (AddedBondList[Binder->nr] == NULL) { 3464 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3465 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3466 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3467 AddedBondList[Binder->nr]->Type = Binder->Type; 3468 } else { 3469 3469 #ifdef ADDHYDROGEN 3470 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3471 exit(1);3470 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3471 exit(1); 3472 3472 #endif 3473 }3474 }3475 }3476 } else {3477 *out << Verbose(3) << "Not Adding, has already been visited." << endl;3478 // This has to be a cyclic bond, check whether it's present ...3479 if (AddedBondList[Binder->nr] == NULL) {3480 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {3481 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3482 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3483 AddedBondList[Binder->nr]->Type = Binder->Type;3484 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)3473 } 3474 } 3475 } 3476 } else { 3477 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3478 // This has to be a cyclic bond, check whether it's present ... 3479 if (AddedBondList[Binder->nr] == NULL) { 3480 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3481 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3482 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3483 AddedBondList[Binder->nr]->Type = Binder->Type; 3484 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3485 3485 #ifdef ADDHYDROGEN 3486 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3487 exit(1);3486 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3487 exit(1); 3488 3488 #endif 3489 }3490 }3491 }3492 }3493 }3494 ColorList[Walker->nr] = black;3495 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;3496 }3497 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");3498 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");3499 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");3500 delete(AtomStack);3489 } 3490 } 3491 } 3492 } 3493 } 3494 ColorList[Walker->nr] = black; 3495 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3496 } 3497 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3498 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3499 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3500 delete(AtomStack); 3501 3501 }; 3502 3502 … … 3512 3512 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3513 3513 { 3514 atom *Walker = NULL, *OtherAtom = NULL;3515 bool status = true;3516 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");3517 3518 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;3519 3520 // reset parent list3521 *out << Verbose(3) << "Resetting ParentList." << endl;3522 for (int i=Father->AtomCount;i--;)3523 ParentList[i] = NULL;3524 3525 // fill parent list with sons3526 *out << Verbose(3) << "Filling Parent List." << endl;3527 Walker = start;3528 while (Walker->next != end) {3529 Walker = Walker->next;3530 ParentList[Walker->father->nr] = Walker;3531 // Outputting List for debugging3532 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3533 }3534 3535 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds3536 *out << Verbose(3) << "Creating bonds." << endl;3537 Walker = Father->start;3538 while (Walker->next != Father->end) {3539 Walker = Walker->next;3540 if (ParentList[Walker->nr] != NULL) {3541 if (ParentList[Walker->nr]->father != Walker) {3542 status = false;3543 } else {3544 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {3545 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3546 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond3547 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;3548 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);3549 }3550 }3551 }3552 }3553 }3554 3555 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");3556 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;3557 return status;3514 atom *Walker = NULL, *OtherAtom = NULL; 3515 bool status = true; 3516 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3517 3518 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3519 3520 // reset parent list 3521 *out << Verbose(3) << "Resetting ParentList." << endl; 3522 for (int i=Father->AtomCount;i--;) 3523 ParentList[i] = NULL; 3524 3525 // fill parent list with sons 3526 *out << Verbose(3) << "Filling Parent List." << endl; 3527 Walker = start; 3528 while (Walker->next != end) { 3529 Walker = Walker->next; 3530 ParentList[Walker->father->nr] = Walker; 3531 // Outputting List for debugging 3532 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3533 } 3534 3535 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3536 *out << Verbose(3) << "Creating bonds." << endl; 3537 Walker = Father->start; 3538 while (Walker->next != Father->end) { 3539 Walker = Walker->next; 3540 if (ParentList[Walker->nr] != NULL) { 3541 if (ParentList[Walker->nr]->father != Walker) { 3542 status = false; 3543 } else { 3544 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3545 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3546 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3547 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3548 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3549 } 3550 } 3551 } 3552 } 3553 } 3554 3555 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3556 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3557 return status; 3558 3558 }; 3559 3559 … … 3567 3567 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3568 3568 { 3569 atom *Runner = NULL;3570 int SP, Removal;3571 3572 *out << Verbose(2) << "Looking for removal candidate." << endl;3573 SP = -1; //0;// not -1, so that Root is never removed3574 Removal = -1;3575 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {3576 Runner = FindAtom((*runner));3577 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack3578 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3579 SP = ShortestPathList[(*runner)];3580 Removal = (*runner);3581 }3582 }3583 }3584 return Removal;3569 atom *Runner = NULL; 3570 int SP, Removal; 3571 3572 *out << Verbose(2) << "Looking for removal candidate." << endl; 3573 SP = -1; //0; // not -1, so that Root is never removed 3574 Removal = -1; 3575 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3576 Runner = FindAtom((*runner)); 3577 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3578 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3579 SP = ShortestPathList[(*runner)]; 3580 Removal = (*runner); 3581 } 3582 } 3583 } 3584 return Removal; 3585 3585 }; 3586 3586 … … 3595 3595 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3596 3596 { 3597 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;3598 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");3599 molecule *Leaf = new molecule(elemente);3600 bool LonelyFlag = false;3601 int size;3602 3603 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;3604 3605 Leaf->BondDistance = BondDistance;3606 for(int i=NDIM*2;i--;)3607 Leaf->cell_size[i] = cell_size[i];3608 3609 // initialise SonList (indicates when we need to replace a bond with hydrogen instead)3610 for(int i=AtomCount;i--;)3611 SonList[i] = NULL;3612 3613 // first create the minimal set of atoms from the KeySet3614 size = 0;3615 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {3616 FatherOfRunner = FindAtom((*runner));// find the id3617 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);3618 size++;3619 }3620 3621 // create the bonds between all: Make it an induced subgraph and add hydrogen3622 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;3623 Runner = Leaf->start;3624 while (Runner->next != Leaf->end) {3625 Runner = Runner->next;3626 LonelyFlag = true;3627 FatherOfRunner = Runner->father;3628 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3629 // create all bonds3630 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father3631 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);3632 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;3633 if (SonList[OtherFather->nr] != NULL) {3634 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;3635 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)3636 // *out << Verbose(3) << "Adding Bond: ";3637 // *out <<3638 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);3639 // *out << "." << endl;3640 //NumBonds[Runner->nr]++;3641 } else {3642 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;3643 }3644 LonelyFlag = false;3645 } else {3646 // *out << ", who has no son in this fragment molecule." << endl;3597 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3598 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3599 molecule *Leaf = new molecule(elemente); 3600 bool LonelyFlag = false; 3601 int size; 3602 3603 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3604 3605 Leaf->BondDistance = BondDistance; 3606 for(int i=NDIM*2;i--;) 3607 Leaf->cell_size[i] = cell_size[i]; 3608 3609 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3610 for(int i=AtomCount;i--;) 3611 SonList[i] = NULL; 3612 3613 // first create the minimal set of atoms from the KeySet 3614 size = 0; 3615 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3616 FatherOfRunner = FindAtom((*runner)); // find the id 3617 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3618 size++; 3619 } 3620 3621 // create the bonds between all: Make it an induced subgraph and add hydrogen 3622 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3623 Runner = Leaf->start; 3624 while (Runner->next != Leaf->end) { 3625 Runner = Runner->next; 3626 LonelyFlag = true; 3627 FatherOfRunner = Runner->father; 3628 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3629 // create all bonds 3630 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3631 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3632 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3633 if (SonList[OtherFather->nr] != NULL) { 3634 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3635 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3636 // *out << Verbose(3) << "Adding Bond: "; 3637 // *out << 3638 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3639 // *out << "." << endl; 3640 //NumBonds[Runner->nr]++; 3641 } else { 3642 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3643 } 3644 LonelyFlag = false; 3645 } else { 3646 // *out << ", who has no son in this fragment molecule." << endl; 3647 3647 #ifdef ADDHYDROGEN 3648 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;3649 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))3650 exit(1);3648 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3649 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3650 exit(1); 3651 3651 #endif 3652 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;3653 }3654 }3655 } else {3656 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;3657 }3658 if ((LonelyFlag) && (size > 1)) {3659 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;3660 }3652 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3653 } 3654 } 3655 } else { 3656 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3657 } 3658 if ((LonelyFlag) && (size > 1)) { 3659 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3660 } 3661 3661 #ifdef ADDHYDROGEN 3662 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen3663 Runner = Runner->next;3662 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3663 Runner = Runner->next; 3664 3664 #endif 3665 }3666 Leaf->CreateListOfBondsPerAtom(out);3667 //Leaflet->Leaf->ScanForPeriodicCorrection(out);3668 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");3669 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;3670 return Leaf;3665 } 3666 Leaf->CreateListOfBondsPerAtom(out); 3667 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3668 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3669 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3670 return Leaf; 3671 3671 }; 3672 3672 … … 3674 3674 */ 3675 3675 struct UniqueFragments { 3676 config *configuration;3677 atom *Root;3678 Graph *Leaflet;3679 KeySet *FragmentSet;3680 int ANOVAOrder;3681 int FragmentCounter;3682 int CurrentIndex;3683 double TEFactor;3684 int *ShortestPathList;3685 bool **UsedList;3686 bond **BondsPerSPList;3687 int *BondsPerSPCount;3676 config *configuration; 3677 atom *Root; 3678 Graph *Leaflet; 3679 KeySet *FragmentSet; 3680 int ANOVAOrder; 3681 int FragmentCounter; 3682 int CurrentIndex; 3683 double TEFactor; 3684 int *ShortestPathList; 3685 bool **UsedList; 3686 bond **BondsPerSPList; 3687 int *BondsPerSPCount; 3688 3688 }; 3689 3689 3690 3690 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3691 3691 * -# loops over every possible combination (2^dimension of edge set) 3692 * -# inserts current set, if there's still space left3693 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist3692 * -# inserts current set, if there's still space left 3693 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3694 3694 ance+1 3695 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph3696 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root3695 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3696 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3697 3697 distance) and current set 3698 3698 * \param *out output stream for debugging … … 3704 3704 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3705 3705 { 3706 atom *OtherWalker = NULL;3707 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;3708 int NumCombinations;3709 bool bit;3710 int bits, TouchedIndex, SubSetDimension, SP, Added;3711 int Removal;3712 int SpaceLeft;3713 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");3714 bond *Binder = NULL;3715 bond **BondsList = NULL;3716 KeySetTestPair TestKeySetInsert;3717 3718 NumCombinations = 1 << SetDimension;3719 3720 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen3721 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder3722 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden3723 3724 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;3725 *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;3726 3727 // initialised touched list (stores added atoms on this level)3728 *out << Verbose(1+verbosity) << "Clearing touched list." << endl;3729 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3730 TouchedList[TouchedIndex] = -1;3731 TouchedIndex = 0;3732 3733 // create every possible combination of the endpieces3734 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;3735 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3736 // count the set bit of i3737 bits = 0;3738 for (int j=SetDimension;j--;)3739 bits += (i & (1 << j)) >> j;3740 3741 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;3742 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue3743 // --1-- add this set of the power set of bond partners to the snake stack3744 Added = 0;3745 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3746 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3747 if (bit) {// if bit is set, we add this bond partner3748 OtherWalker = BondsSet[j]->rightatom;// rightatom is always the one more distant, i.e. the one to add3749 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;3750 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;3751 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);3752 if (TestKeySetInsert.second) {3753 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3754 Added++;3755 } else {3756 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;3757 }3758 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;3759 //}3760 } else {3761 *out << Verbose(2+verbosity) << "Not adding." << endl;3762 }3763 }3764 3765 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore3766 if (SpaceLeft > 0) {3767 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;3768 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3769 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion3770 SP = RootDistance+1;// this is the next level3771 // first count the members in the subset3772 SubSetDimension = 0;3773 Binder = FragmentSearch->BondsPerSPList[2*SP];// start node for this level3774 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {// compare to end node of this level3775 Binder = Binder->next;3776 for (int k=TouchedIndex;k--;) {3777 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3778 SubSetDimension++;3779 }3780 }3781 // then allocate and fill the list3782 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");3783 SubSetDimension = 0;3784 Binder = FragmentSearch->BondsPerSPList[2*SP];3785 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {3786 Binder = Binder->next;3787 for (int k=0;k<TouchedIndex;k++) {3788 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3789 BondsList[SubSetDimension++] = Binder;3790 }3791 }3792 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;3793 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);3794 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");3795 }3796 } else {3797 // --2-- otherwise store the complete fragment3798 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;3799 // store fragment as a KeySet3800 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";3801 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3802 *out << (*runner) << " ";3803 *out << endl;3804 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))3805 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;3806 InsertFragmentIntoGraph(out, FragmentSearch);3807 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);3808 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);3809 }3810 3811 // --3-- remove all added items in this level from snake stack3812 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;3813 for(int j=0;j<TouchedIndex;j++) {3814 Removal = TouchedList[j];3815 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;3816 FragmentSearch->FragmentSet->erase(Removal);3817 TouchedList[j] = -1;3818 }3819 *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";3820 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3821 *out << (*runner) << " ";3822 *out << endl;3823 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level3824 } else {3825 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;3826 }3827 }3828 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");3829 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;3706 atom *OtherWalker = NULL; 3707 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3708 int NumCombinations; 3709 bool bit; 3710 int bits, TouchedIndex, SubSetDimension, SP, Added; 3711 int Removal; 3712 int SpaceLeft; 3713 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3714 bond *Binder = NULL; 3715 bond **BondsList = NULL; 3716 KeySetTestPair TestKeySetInsert; 3717 3718 NumCombinations = 1 << SetDimension; 3719 3720 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3721 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3722 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3723 3724 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3725 *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; 3726 3727 // initialised touched list (stores added atoms on this level) 3728 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3729 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3730 TouchedList[TouchedIndex] = -1; 3731 TouchedIndex = 0; 3732 3733 // create every possible combination of the endpieces 3734 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3735 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3736 // count the set bit of i 3737 bits = 0; 3738 for (int j=SetDimension;j--;) 3739 bits += (i & (1 << j)) >> j; 3740 3741 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3742 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3743 // --1-- add this set of the power set of bond partners to the snake stack 3744 Added = 0; 3745 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3746 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3747 if (bit) { // if bit is set, we add this bond partner 3748 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3749 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3750 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3751 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3752 if (TestKeySetInsert.second) { 3753 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3754 Added++; 3755 } else { 3756 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3757 } 3758 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3759 //} 3760 } else { 3761 *out << Verbose(2+verbosity) << "Not adding." << endl; 3762 } 3763 } 3764 3765 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3766 if (SpaceLeft > 0) { 3767 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3768 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3769 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3770 SP = RootDistance+1; // this is the next level 3771 // first count the members in the subset 3772 SubSetDimension = 0; 3773 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3774 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3775 Binder = Binder->next; 3776 for (int k=TouchedIndex;k--;) { 3777 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3778 SubSetDimension++; 3779 } 3780 } 3781 // then allocate and fill the list 3782 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3783 SubSetDimension = 0; 3784 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3785 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3786 Binder = Binder->next; 3787 for (int k=0;k<TouchedIndex;k++) { 3788 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3789 BondsList[SubSetDimension++] = Binder; 3790 } 3791 } 3792 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3793 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3794 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3795 } 3796 } else { 3797 // --2-- otherwise store the complete fragment 3798 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3799 // store fragment as a KeySet 3800 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3801 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3802 *out << (*runner) << " "; 3803 *out << endl; 3804 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3805 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3806 InsertFragmentIntoGraph(out, FragmentSearch); 3807 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3808 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3809 } 3810 3811 // --3-- remove all added items in this level from snake stack 3812 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3813 for(int j=0;j<TouchedIndex;j++) { 3814 Removal = TouchedList[j]; 3815 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3816 FragmentSearch->FragmentSet->erase(Removal); 3817 TouchedList[j] = -1; 3818 } 3819 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3820 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3821 *out << (*runner) << " "; 3822 *out << endl; 3823 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3824 } else { 3825 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3826 } 3827 } 3828 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3829 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3830 3830 }; 3831 3831 … … 3838 3838 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3839 3839 { 3840 atom *Walker = NULL, *Walker2 = NULL;3841 bool BondStatus = false;3842 int size;3843 3844 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;3845 *out << Verbose(2) << "Disconnected atom: ";3846 3847 // count number of atoms in graph3848 size = 0;3849 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)3850 size++;3851 if (size > 1)3852 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {3853 Walker = FindAtom(*runner);3854 BondStatus = false;3855 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {3856 Walker2 = FindAtom(*runners);3857 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {3858 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {3859 BondStatus = true;3860 break;3861 }3862 if (BondStatus)3863 break;3864 }3865 }3866 if (!BondStatus) {3867 *out << (*Walker) << endl;3868 return false;3869 }3870 }3871 else {3872 *out << "none." << endl;3873 return true;3874 }3875 *out << "none." << endl;3876 3877 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;3878 3879 return true;3840 atom *Walker = NULL, *Walker2 = NULL; 3841 bool BondStatus = false; 3842 int size; 3843 3844 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3845 *out << Verbose(2) << "Disconnected atom: "; 3846 3847 // count number of atoms in graph 3848 size = 0; 3849 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 3850 size++; 3851 if (size > 1) 3852 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 3853 Walker = FindAtom(*runner); 3854 BondStatus = false; 3855 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 3856 Walker2 = FindAtom(*runners); 3857 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 3858 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 3859 BondStatus = true; 3860 break; 3861 } 3862 if (BondStatus) 3863 break; 3864 } 3865 } 3866 if (!BondStatus) { 3867 *out << (*Walker) << endl; 3868 return false; 3869 } 3870 } 3871 else { 3872 *out << "none." << endl; 3873 return true; 3874 } 3875 *out << "none." << endl; 3876 3877 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 3878 3879 return true; 3880 3880 } 3881 3881 … … 3897 3897 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 3898 3898 { 3899 int SP, AtomKeyNr;3900 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;3901 bond *Binder = NULL;3902 bond *CurrentEdge = NULL;3903 bond **BondsList = NULL;3904 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;3905 int Counter = FragmentSearch.FragmentCounter;3906 int RemainingWalkers;3907 3908 *out << endl;3909 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;3910 3911 // prepare Label and SP arrays of the BFS search3912 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;3913 3914 // prepare root level (SP = 0) and a loop bond denoting Root3915 for (int i=1;i<Order;i++)3916 FragmentSearch.BondsPerSPCount[i] = 0;3917 FragmentSearch.BondsPerSPCount[0] = 1;3918 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);3919 add(Binder, FragmentSearch.BondsPerSPList[1]);3920 3921 // do a BFS search to fill the SP lists and label the found vertices3922 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into3923 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning3924 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth3925 // (EdgeinSPLevel) of this tree ...3926 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence3927 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.3928 *out << endl;3929 *out << Verbose(0) << "Starting BFS analysis ..." << endl;3930 for (SP = 0; SP < (Order-1); SP++) {3931 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";3932 if (SP > 0) {3933 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;3934 FragmentSearch.BondsPerSPCount[SP] = 0;3935 } else3936 *out << "." << endl;3937 3938 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];3939 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list3940 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list3941 CurrentEdge = CurrentEdge->next;3942 RemainingWalkers--;3943 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant3944 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor3945 AtomKeyNr = Walker->nr;3946 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;3947 // check for new sp level3948 // go through all its bonds3949 *out << Verbose(1) << "Going through all bonds of Walker." << endl;3950 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {3951 Binder = ListOfBondsPerAtom[AtomKeyNr][i];3952 OtherWalker = Binder->GetOtherAtom(Walker);3953 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())3954 #ifdef ADDHYDROGEN3955 && (OtherWalker->type->Z != 1)3956 #endif3957 ) {// skip hydrogens and restrict to fragment3958 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;3959 // set the label if not set (and push on root stack as well)3960 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's3961 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;3962 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;3963 // add the bond in between to the SP list3964 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant3965 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);3966 FragmentSearch.BondsPerSPCount[SP+1]++;3967 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;3968 } else {3969 if (OtherWalker != Predecessor)3970 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;3971 else3972 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;3973 }3974 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;3975 }3976 }3977 }3978 3979 // outputting all list for debugging3980 *out << Verbose(0) << "Printing all found lists." << endl;3981 for(int i=1;i<Order;i++) {// skip the root edge in the printing3982 Binder = FragmentSearch.BondsPerSPList[2*i];3983 *out << Verbose(1) << "Current SP level is " << i << "." << endl;3984 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {3985 Binder = Binder->next;3986 *out << Verbose(2) << *Binder << endl;3987 }3988 }3989 3990 // creating fragments with the found edge sets(may be done in reverse order, faster)3991 SP = -1;// the Root <-> Root edge must be subtracted!3992 for(int i=Order;i--;) { // sum up all found edges3993 Binder = FragmentSearch.BondsPerSPList[2*i];3994 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {3995 Binder = Binder->next;3996 SP ++;3997 }3998 }3999 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;4000 if (SP >= (Order-1)) {4001 // start with root (push on fragment stack)4002 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;4003 FragmentSearch.FragmentSet->clear();4004 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;4005 // prepare the subset and call the generator4006 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");4007 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4008 4009 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);4010 4011 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");4012 } else {4013 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;4014 }4015 4016 // as FragmentSearch structure is used only once, we don't have to clean it anymore4017 // remove root from stack4018 *out << Verbose(0) << "Removing root again from stack." << endl;4019 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);4020 4021 // free'ing the bonds lists4022 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;4023 for(int i=Order;i--;) {4024 *out << Verbose(1) << "Current SP level is " << i << ": ";4025 Binder = FragmentSearch.BondsPerSPList[2*i];4026 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4027 Binder = Binder->next;4028 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local4029 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;4030 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;4031 }4032 // delete added bonds4033 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);4034 // also start and end node4035 *out << "cleaned." << endl;4036 }4037 4038 // return list4039 *out << Verbose(0) << "End of PowerSetGenerator." << endl;4040 return (FragmentSearch.FragmentCounter - Counter);3899 int SP, AtomKeyNr; 3900 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 3901 bond *Binder = NULL; 3902 bond *CurrentEdge = NULL; 3903 bond **BondsList = NULL; 3904 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 3905 int Counter = FragmentSearch.FragmentCounter; 3906 int RemainingWalkers; 3907 3908 *out << endl; 3909 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3910 3911 // prepare Label and SP arrays of the BFS search 3912 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 3913 3914 // prepare root level (SP = 0) and a loop bond denoting Root 3915 for (int i=1;i<Order;i++) 3916 FragmentSearch.BondsPerSPCount[i] = 0; 3917 FragmentSearch.BondsPerSPCount[0] = 1; 3918 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 3919 add(Binder, FragmentSearch.BondsPerSPList[1]); 3920 3921 // do a BFS search to fill the SP lists and label the found vertices 3922 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 3923 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 3924 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 3925 // (EdgeinSPLevel) of this tree ... 3926 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 3927 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 3928 *out << endl; 3929 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3930 for (SP = 0; SP < (Order-1); SP++) { 3931 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 3932 if (SP > 0) { 3933 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3934 FragmentSearch.BondsPerSPCount[SP] = 0; 3935 } else 3936 *out << "." << endl; 3937 3938 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 3939 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 3940 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 3941 CurrentEdge = CurrentEdge->next; 3942 RemainingWalkers--; 3943 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 3944 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 3945 AtomKeyNr = Walker->nr; 3946 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 3947 // check for new sp level 3948 // go through all its bonds 3949 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3950 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3951 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3952 OtherWalker = Binder->GetOtherAtom(Walker); 3953 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3954 #ifdef ADDHYDROGEN 3955 && (OtherWalker->type->Z != 1) 3956 #endif 3957 ) { // skip hydrogens and restrict to fragment 3958 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 3959 // set the label if not set (and push on root stack as well) 3960 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 3961 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 3962 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3963 // add the bond in between to the SP list 3964 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 3965 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 3966 FragmentSearch.BondsPerSPCount[SP+1]++; 3967 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 3968 } else { 3969 if (OtherWalker != Predecessor) 3970 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 3971 else 3972 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 3973 } 3974 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 3975 } 3976 } 3977 } 3978 3979 // outputting all list for debugging 3980 *out << Verbose(0) << "Printing all found lists." << endl; 3981 for(int i=1;i<Order;i++) { // skip the root edge in the printing 3982 Binder = FragmentSearch.BondsPerSPList[2*i]; 3983 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3984 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3985 Binder = Binder->next; 3986 *out << Verbose(2) << *Binder << endl; 3987 } 3988 } 3989 3990 // creating fragments with the found edge sets (may be done in reverse order, faster) 3991 SP = -1; // the Root <-> Root edge must be subtracted! 3992 for(int i=Order;i--;) { // sum up all found edges 3993 Binder = FragmentSearch.BondsPerSPList[2*i]; 3994 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3995 Binder = Binder->next; 3996 SP ++; 3997 } 3998 } 3999 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 4000 if (SP >= (Order-1)) { 4001 // start with root (push on fragment stack) 4002 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4003 FragmentSearch.FragmentSet->clear(); 4004 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4005 // prepare the subset and call the generator 4006 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4007 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4008 4009 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4010 4011 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4012 } else { 4013 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4014 } 4015 4016 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4017 // remove root from stack 4018 *out << Verbose(0) << "Removing root again from stack." << endl; 4019 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4020 4021 // free'ing the bonds lists 4022 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4023 for(int i=Order;i--;) { 4024 *out << Verbose(1) << "Current SP level is " << i << ": "; 4025 Binder = FragmentSearch.BondsPerSPList[2*i]; 4026 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4027 Binder = Binder->next; 4028 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4029 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4030 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4031 } 4032 // delete added bonds 4033 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4034 // also start and end node 4035 *out << "cleaned." << endl; 4036 } 4037 4038 // return list 4039 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4040 return (FragmentSearch.FragmentCounter - Counter); 4041 4041 }; 4042 4042 … … 4049 4049 void molecule::ScanForPeriodicCorrection(ofstream *out) 4050 4050 { 4051 bond *Binder = NULL;4052 bond *OtherBinder = NULL;4053 atom *Walker = NULL;4054 atom *OtherWalker = NULL;4055 double *matrix = ReturnFullMatrixforSymmetric(cell_size);4056 enum Shading *ColorList = NULL;4057 double tmp;4058 Vector Translationvector;4059 //class StackClass<atom *> *CompStack = NULL;4060 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);4061 bool flag = true;4062 4063 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;4064 4065 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");4066 while (flag) {4067 // remove bonds that are beyond bonddistance4068 for(int i=NDIM;i--;)4069 Translationvector.x[i] = 0.;4070 // scan all bonds4071 Binder = first;4072 flag = false;4073 while ((!flag) && (Binder->next != last)) {4074 Binder = Binder->next;4075 for (int i=NDIM;i--;) {4076 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);4077 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;4078 if (tmp > BondDistance) {4079 OtherBinder = Binder->next; // note down binding partner for later re-insertion4080 unlink(Binder);// unlink bond4081 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;4082 flag = true;4083 break;4084 }4085 }4086 }4087 if (flag) {4088 // create translation vector from their periodically modified distance4089 for (int i=NDIM;i--;) {4090 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];4091 if (fabs(tmp) > BondDistance)4092 Translationvector.x[i] = (tmp < 0) ? +1. : -1.;4093 }4094 Translationvector.MatrixMultiplication(matrix);4095 //*out << Verbose(3) << "Translation vector is ";4096 Translationvector.Output(out);4097 *out << endl;4098 // apply to all atoms of first component via BFS4099 for (int i=AtomCount;i--;)4100 ColorList[i] = white;4101 AtomStack->Push(Binder->leftatom);4102 while (!AtomStack->IsEmpty()) {4103 Walker = AtomStack->PopFirst();4104 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;4105 ColorList[Walker->nr] = black;// mark as explored4106 Walker->x.AddVector(&Translationvector); // translate4107 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4108 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {4109 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);4110 if (ColorList[OtherWalker->nr] == white) {4111 AtomStack->Push(OtherWalker); // push if yet unexplored4112 }4113 }4114 }4115 }4116 // re-add bond4117 link(Binder, OtherBinder);4118 } else {4119 *out << Verbose(3) << "No corrections for this fragment." << endl;4120 }4121 //delete(CompStack);4122 }4123 4124 // free allocated space from ReturnFullMatrixforSymmetric()4125 delete(AtomStack);4126 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");4127 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");4128 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;4051 bond *Binder = NULL; 4052 bond *OtherBinder = NULL; 4053 atom *Walker = NULL; 4054 atom *OtherWalker = NULL; 4055 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4056 enum Shading *ColorList = NULL; 4057 double tmp; 4058 Vector Translationvector; 4059 //class StackClass<atom *> *CompStack = NULL; 4060 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4061 bool flag = true; 4062 4063 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4064 4065 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4066 while (flag) { 4067 // remove bonds that are beyond bonddistance 4068 for(int i=NDIM;i--;) 4069 Translationvector.x[i] = 0.; 4070 // scan all bonds 4071 Binder = first; 4072 flag = false; 4073 while ((!flag) && (Binder->next != last)) { 4074 Binder = Binder->next; 4075 for (int i=NDIM;i--;) { 4076 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4077 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4078 if (tmp > BondDistance) { 4079 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4080 unlink(Binder); // unlink bond 4081 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4082 flag = true; 4083 break; 4084 } 4085 } 4086 } 4087 if (flag) { 4088 // create translation vector from their periodically modified distance 4089 for (int i=NDIM;i--;) { 4090 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4091 if (fabs(tmp) > BondDistance) 4092 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4093 } 4094 Translationvector.MatrixMultiplication(matrix); 4095 //*out << Verbose(3) << "Translation vector is "; 4096 Translationvector.Output(out); 4097 *out << endl; 4098 // apply to all atoms of first component via BFS 4099 for (int i=AtomCount;i--;) 4100 ColorList[i] = white; 4101 AtomStack->Push(Binder->leftatom); 4102 while (!AtomStack->IsEmpty()) { 4103 Walker = AtomStack->PopFirst(); 4104 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4105 ColorList[Walker->nr] = black; // mark as explored 4106 Walker->x.AddVector(&Translationvector); // translate 4107 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4108 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4109 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4110 if (ColorList[OtherWalker->nr] == white) { 4111 AtomStack->Push(OtherWalker); // push if yet unexplored 4112 } 4113 } 4114 } 4115 } 4116 // re-add bond 4117 link(Binder, OtherBinder); 4118 } else { 4119 *out << Verbose(3) << "No corrections for this fragment." << endl; 4120 } 4121 //delete(CompStack); 4122 } 4123 4124 // free allocated space from ReturnFullMatrixforSymmetric() 4125 delete(AtomStack); 4126 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4127 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4128 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4129 4129 }; 4130 4130 … … 4135 4135 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4136 4136 { 4137 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");4138 matrix[0] = symm[0];4139 matrix[1] = symm[1];4140 matrix[2] = symm[3];4141 matrix[3] = symm[1];4142 matrix[4] = symm[2];4143 matrix[5] = symm[4];4144 matrix[6] = symm[3];4145 matrix[7] = symm[4];4146 matrix[8] = symm[5];4147 return matrix;4137 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4138 matrix[0] = symm[0]; 4139 matrix[1] = symm[1]; 4140 matrix[2] = symm[3]; 4141 matrix[3] = symm[1]; 4142 matrix[4] = symm[2]; 4143 matrix[5] = symm[4]; 4144 matrix[6] = symm[3]; 4145 matrix[7] = symm[4]; 4146 matrix[8] = symm[5]; 4147 return matrix; 4148 4148 }; 4149 4149 4150 4150 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4151 4151 { 4152 //cout << "my check is used." << endl;4153 if (SubgraphA.size() < SubgraphB.size()) {4154 return true;4155 } else {4156 if (SubgraphA.size() > SubgraphB.size()) {4157 return false;4158 } else {4159 KeySet::iterator IteratorA = SubgraphA.begin();4160 KeySet::iterator IteratorB = SubgraphB.begin();4161 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {4162 if ((*IteratorA) <(*IteratorB))4163 return true;4164 else if ((*IteratorA) > (*IteratorB)) {4165 return false;4166 } // else, go on to next index4167 IteratorA++;4168 IteratorB++;4169 } // end of while loop4170 }// end of check in case of equal sizes4171 }4172 return false; // if we reach this point, they are equal4152 //cout << "my check is used." << endl; 4153 if (SubgraphA.size() < SubgraphB.size()) { 4154 return true; 4155 } else { 4156 if (SubgraphA.size() > SubgraphB.size()) { 4157 return false; 4158 } else { 4159 KeySet::iterator IteratorA = SubgraphA.begin(); 4160 KeySet::iterator IteratorB = SubgraphB.begin(); 4161 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4162 if ((*IteratorA) < (*IteratorB)) 4163 return true; 4164 else if ((*IteratorA) > (*IteratorB)) { 4165 return false; 4166 } // else, go on to next index 4167 IteratorA++; 4168 IteratorB++; 4169 } // end of while loop 4170 }// end of check in case of equal sizes 4171 } 4172 return false; // if we reach this point, they are equal 4173 4173 }; 4174 4174 4175 4175 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4176 4176 //{ 4177 // return KeyCompare(SubgraphA, SubgraphB);4177 // return KeyCompare(SubgraphA, SubgraphB); 4178 4178 //}; 4179 4179 … … 4187 4187 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4188 4188 { 4189 GraphTestPair testGraphInsert;4190 4191 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4192 if (testGraphInsert.second) {4193 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;4194 Fragment->FragmentCounter++;4195 } else {4196 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4197 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4198 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;4199 }4189 GraphTestPair testGraphInsert; 4190 4191 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4192 if (testGraphInsert.second) { 4193 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4194 Fragment->FragmentCounter++; 4195 } else { 4196 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4197 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4198 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4199 } 4200 4200 }; 4201 4201 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4202 4202 //{ 4203 // // copy stack contents to set and call overloaded function again4204 // KeySet set;4205 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)4206 // set.insert((*runner));4207 // InsertIntoGraph(out, set, graph, counter, factor);4203 // // copy stack contents to set and call overloaded function again 4204 // KeySet set; 4205 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4206 // set.insert((*runner)); 4207 // InsertIntoGraph(out, set, graph, counter, factor); 4208 4208 //}; 4209 4209 … … 4216 4216 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4217 4217 { 4218 GraphTestPair testGraphInsert;4219 4220 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {4221 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4222 if (testGraphInsert.second) {4223 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;4224 } else {4225 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4226 ((*(testGraphInsert.first)).second).second += (*runner).second.second;4227 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;4228 }4229 }4218 GraphTestPair testGraphInsert; 4219 4220 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4221 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4222 if (testGraphInsert.second) { 4223 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4224 } else { 4225 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4226 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4227 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4228 } 4229 } 4230 4230 }; 4231 4231 … … 4234 4234 * -# constructs a complete keyset of the molecule 4235 4235 * -# In a loop over all possible roots from the given rootstack 4236 * -# increases order of root site4237 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr4238 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset4236 * -# increases order of root site 4237 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4238 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4239 4239 as the restricted one and each site in the set as the root) 4240 * -# these are merged into a fragment list of keysets4240 * -# these are merged into a fragment list of keysets 4241 4241 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4242 4242 * Important only is that we create all fragments, it is not important if we create them more than once … … 4250 4250 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4251 4251 { 4252 Graph ***FragmentLowerOrdersList = NULL;4253 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;4254 int counter = 0, Order;4255 int UpgradeCount = RootStack.size();4256 KeyStack FragmentRootStack;4257 int RootKeyNr, RootNr;4258 struct UniqueFragments FragmentSearch;4259 4260 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;4261 4262 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)4263 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)4264 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4265 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4266 4267 // initialise the fragments structure4268 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");4269 FragmentSearch.FragmentCounter = 0;4270 FragmentSearch.FragmentSet = new KeySet;4271 FragmentSearch.Root = FindAtom(RootKeyNr);4272 for (int i=AtomCount;i--;) {4273 FragmentSearch.ShortestPathList[i] = -1;4274 }4275 4276 // Construct the complete KeySet which we need for topmost level only (but for all Roots)4277 atom *Walker = start;4278 KeySet CompleteMolecule;4279 while (Walker->next != end) {4280 Walker = Walker->next;4281 CompleteMolecule.insert(Walker->GetTrueFather()->nr);4282 }4283 4284 // 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, as4285 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th),4286 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])4287 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster)4288 RootNr = 0;// counts through the roots in RootStack4289 while ((RootNr < UpgradeCount) && (!RootStack.empty())) {4290 RootKeyNr = RootStack.front();4291 RootStack.pop_front();4292 Walker = FindAtom(RootKeyNr);4293 // check cyclic lengths4294 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {4295 //*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;4296 //} else4297 {4298 // increase adaptive order by one4299 Walker->GetTrueFather()->AdaptiveOrder++;4300 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;4301 4302 // initialise Order-dependent entries of UniqueFragments structure4303 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");4304 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");4305 for (int i=Order;i--;) {4306 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4307 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4308 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4309 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];4310 FragmentSearch.BondsPerSPCount[i] = 0;4311 }4312 4313 // allocate memory for all lower level orders in this 1D-array of ptrs4314 NumLevels = 1 << (Order-1); // (int)pow(2,Order);4315 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4316 for (int i=0;i<NumLevels;i++)4317 FragmentLowerOrdersList[RootNr][i] = NULL;4318 4319 // create top order where nothing is reduced4320 *out << Verbose(0) << "==============================================================================================================" << endl;4321 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "4322 4323 // Create list of Graphs of current Bond Order (i.e. F_{ij})4324 FragmentLowerOrdersList[RootNr][0] =new Graph;4325 FragmentSearch.TEFactor = 1.;4326 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4327 FragmentSearch.Root = Walker;4328 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);4329 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4330 if (NumMoleculesOfOrder[RootNr] != 0) {4331 NumMolecules = 0;4332 4333 // we don't have to dive into suborders! These keysets are all already created on lower orders!4334 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)4335 4336 // if ((NumLevels >> 1) > 0) {4337 // // create lower order fragments4338 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;4339 // Order = Walker->AdaptiveOrder;4340 // 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)4341 // // step down to next order at (virtual) boundary of powers of 2 in array4342 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))4343 // Order--;4344 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl;4345 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {4346 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));4347 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;4348 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;4252 Graph ***FragmentLowerOrdersList = NULL; 4253 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4254 int counter = 0, Order; 4255 int UpgradeCount = RootStack.size(); 4256 KeyStack FragmentRootStack; 4257 int RootKeyNr, RootNr; 4258 struct UniqueFragments FragmentSearch; 4259 4260 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4261 4262 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4263 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4264 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4265 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4266 4267 // initialise the fragments structure 4268 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4269 FragmentSearch.FragmentCounter = 0; 4270 FragmentSearch.FragmentSet = new KeySet; 4271 FragmentSearch.Root = FindAtom(RootKeyNr); 4272 for (int i=AtomCount;i--;) { 4273 FragmentSearch.ShortestPathList[i] = -1; 4274 } 4275 4276 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4277 atom *Walker = start; 4278 KeySet CompleteMolecule; 4279 while (Walker->next != end) { 4280 Walker = Walker->next; 4281 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4282 } 4283 4284 // 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 4285 // each has to be split up. E.g. for the second level we have one from 5th, one from 4th, two from 3th (which in turn is one from 5th, one from 4th), 4286 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4287 // with the order along the cells as this: 5433222211111111 for BondOrder 5 needing 16=pow(2,5-1) cells (only we use bit-shifting which is faster) 4288 RootNr = 0; // counts through the roots in RootStack 4289 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4290 RootKeyNr = RootStack.front(); 4291 RootStack.pop_front(); 4292 Walker = FindAtom(RootKeyNr); 4293 // check cyclic lengths 4294 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4295 // *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; 4296 //} else 4297 { 4298 // increase adaptive order by one 4299 Walker->GetTrueFather()->AdaptiveOrder++; 4300 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4301 4302 // initialise Order-dependent entries of UniqueFragments structure 4303 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4304 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4305 for (int i=Order;i--;) { 4306 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4307 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4308 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4309 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4310 FragmentSearch.BondsPerSPCount[i] = 0; 4311 } 4312 4313 // allocate memory for all lower level orders in this 1D-array of ptrs 4314 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4315 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4316 for (int i=0;i<NumLevels;i++) 4317 FragmentLowerOrdersList[RootNr][i] = NULL; 4318 4319 // create top order where nothing is reduced 4320 *out << Verbose(0) << "==============================================================================================================" << endl; 4321 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4322 4323 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4324 FragmentLowerOrdersList[RootNr][0] = new Graph; 4325 FragmentSearch.TEFactor = 1.; 4326 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4327 FragmentSearch.Root = Walker; 4328 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4329 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4330 if (NumMoleculesOfOrder[RootNr] != 0) { 4331 NumMolecules = 0; 4332 4333 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4334 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4335 4336 // if ((NumLevels >> 1) > 0) { 4337 // // create lower order fragments 4338 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4339 // Order = Walker->AdaptiveOrder; 4340 // 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) 4341 // // step down to next order at (virtual) boundary of powers of 2 in array 4342 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4343 // Order--; 4344 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4345 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4346 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4347 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4348 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4349 4349 // 4350 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules4351 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;4352 // //NumMolecules = 0;4353 // FragmentLowerOrdersList[RootNr][dest] = new Graph;4354 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {4355 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {4356 // Graph TempFragmentList;4357 // FragmentSearch.TEFactor = -(*runner).second.second;4358 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4359 // FragmentSearch.Root = FindAtom(*sprinter);4360 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);4361 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]4362 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;4363 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);4364 // }4365 // }4366 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;4367 // }4368 // }4369 // }4370 } else {4371 Walker->GetTrueFather()->MaxOrder = true;4372 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;4373 }4374 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder4375 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;4376 TotalNumMolecules += NumMoleculesOfOrder[RootNr];4377 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4378 RootStack.push_back(RootKeyNr); // put back on stack4379 RootNr++;4380 4381 // free Order-dependent entries of UniqueFragments structure for next loop cycle4382 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");4383 for (int i=Order;i--;) {4384 delete(FragmentSearch.BondsPerSPList[2*i]);4385 delete(FragmentSearch.BondsPerSPList[2*i+1]);4386 }4387 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");4388 }4389 }4390 *out << Verbose(0) << "==============================================================================================================" << endl;4391 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;4392 *out << Verbose(0) << "==============================================================================================================" << endl;4393 4394 // cleanup FragmentSearch structure4395 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");4396 delete(FragmentSearch.FragmentSet);4397 4398 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)4399 // 54332222111111114400 // 432211114401 // 32114402 // 214403 // 14404 4405 // Subsequently, we combine all into a single list (FragmentList)4406 4407 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;4408 if (FragmentList == NULL) {4409 FragmentList = new Graph;4410 counter = 0;4411 } else {4412 counter = FragmentList->size();4413 }4414 RootNr = 0;4415 while (!RootStack.empty()) {4416 RootKeyNr = RootStack.front();4417 RootStack.pop_front();4418 Walker = FindAtom(RootKeyNr);4419 NumLevels = 1 << (Walker->AdaptiveOrder - 1);4420 for(int i=0;i<NumLevels;i++) {4421 if (FragmentLowerOrdersList[RootNr][i] != NULL) {4422 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);4423 delete(FragmentLowerOrdersList[RootNr][i]);4424 }4425 }4426 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4427 RootNr++;4428 }4429 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4430 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4431 4432 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;4350 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4351 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4352 // //NumMolecules = 0; 4353 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4354 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4355 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4356 // Graph TempFragmentList; 4357 // FragmentSearch.TEFactor = -(*runner).second.second; 4358 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4359 // FragmentSearch.Root = FindAtom(*sprinter); 4360 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4361 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4362 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4363 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4364 // } 4365 // } 4366 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4367 // } 4368 // } 4369 // } 4370 } else { 4371 Walker->GetTrueFather()->MaxOrder = true; 4372 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4373 } 4374 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4375 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4376 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4377 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4378 RootStack.push_back(RootKeyNr); // put back on stack 4379 RootNr++; 4380 4381 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4382 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4383 for (int i=Order;i--;) { 4384 delete(FragmentSearch.BondsPerSPList[2*i]); 4385 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4386 } 4387 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4388 } 4389 } 4390 *out << Verbose(0) << "==============================================================================================================" << endl; 4391 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4392 *out << Verbose(0) << "==============================================================================================================" << endl; 4393 4394 // cleanup FragmentSearch structure 4395 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4396 delete(FragmentSearch.FragmentSet); 4397 4398 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4399 // 5433222211111111 4400 // 43221111 4401 // 3211 4402 // 21 4403 // 1 4404 4405 // Subsequently, we combine all into a single list (FragmentList) 4406 4407 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4408 if (FragmentList == NULL) { 4409 FragmentList = new Graph; 4410 counter = 0; 4411 } else { 4412 counter = FragmentList->size(); 4413 } 4414 RootNr = 0; 4415 while (!RootStack.empty()) { 4416 RootKeyNr = RootStack.front(); 4417 RootStack.pop_front(); 4418 Walker = FindAtom(RootKeyNr); 4419 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4420 for(int i=0;i<NumLevels;i++) { 4421 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4422 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4423 delete(FragmentLowerOrdersList[RootNr][i]); 4424 } 4425 } 4426 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4427 RootNr++; 4428 } 4429 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4430 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4431 4432 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4433 4433 }; 4434 4434 … … 4440 4440 inline int CompareDoubles (const void * a, const void * b) 4441 4441 { 4442 if (*(double *)a > *(double *)b)4443 return -1;4444 else if (*(double *)a < *(double *)b)4445 return 1;4446 else4447 return 0;4442 if (*(double *)a > *(double *)b) 4443 return -1; 4444 else if (*(double *)a < *(double *)b) 4445 return 1; 4446 else 4447 return 0; 4448 4448 }; 4449 4449 … … 4456 4456 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4457 4457 { 4458 int flag;4459 double *Distances = NULL, *OtherDistances = NULL;4460 Vector CenterOfGravity, OtherCenterOfGravity;4461 size_t *PermMap = NULL, *OtherPermMap = NULL;4462 int *PermutationMap = NULL;4463 atom *Walker = NULL;4464 bool result = true; // status of comparison4465 4466 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;4467 /// first count both their atoms and elements and update lists thereby ...4468 //*out << Verbose(0) << "Counting atoms, updating list" << endl;4469 CountAtoms(out);4470 OtherMolecule->CountAtoms(out);4471 CountElements();4472 OtherMolecule->CountElements();4473 4474 /// ... and compare:4475 /// -# AtomCount4476 if (result) {4477 if (AtomCount != OtherMolecule->AtomCount) {4478 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4479 result = false;4480 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4481 }4482 /// -# ElementCount4483 if (result) {4484 if (ElementCount != OtherMolecule->ElementCount) {4485 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4486 result = false;4487 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4488 }4489 /// -# ElementsInMolecule4490 if (result) {4491 for (flag=MAX_ELEMENTS;flag--;) {4492 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4493 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])4494 break;4495 }4496 if (flag < MAX_ELEMENTS) {4497 *out << Verbose(4) << "ElementsInMolecule don't match." << endl;4498 result = false;4499 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;4500 }4501 /// then determine and compare center of gravity for each molecule ...4502 if (result) {4503 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;4504 DeterminePeriodicCenter(CenterOfGravity);4505 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity);4506 *out << Verbose(5) << "Center of Gravity: ";4507 CenterOfGravity.Output(out);4508 *out << endl << Verbose(5) << "Other Center of Gravity: ";4509 OtherCenterOfGravity.Output(out);4510 *out << endl;4511 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {4512 *out << Verbose(4) << "Centers of gravity don't match." << endl;4513 result = false;4514 }4515 }4516 4517 /// ... then make a list with the euclidian distance to this center for each atom of both molecules4518 if (result) {4519 *out << Verbose(5) << "Calculating distances" << endl;4520 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");4521 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");4522 Walker = start;4523 while (Walker->next != end) {4524 Walker = Walker->next;4525 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);4526 }4527 Walker = OtherMolecule->start;4528 while (Walker->next != OtherMolecule->end) {4529 Walker = Walker->next;4530 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);4531 }4532 4533 /// ... sort each list (using heapsort (o(N log N)) from GSL)4534 *out << Verbose(5) << "Sorting distances" << endl;4535 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");4536 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4537 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);4538 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);4539 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");4540 *out << Verbose(5) << "Combining Permutation Maps" << endl;4541 for(int i=AtomCount;i--;)4542 PermutationMap[PermMap[i]] = (int) OtherPermMap[i];4543 4544 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all4545 *out << Verbose(4) << "Comparing distances" << endl;4546 flag = 0;4547 for (int i=0;i<AtomCount;i++) {4548 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4549 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)4550 flag = 1;4551 }4552 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");4553 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4554 4555 /// free memory4556 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");4557 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");4558 if (flag) { // if not equal4559 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");4560 result = false;4561 }4562 }4563 /// return pointer to map if all distances were below \a threshold4564 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;4565 if (result) {4566 *out << Verbose(3) << "Result: Equal." << endl;4567 return PermutationMap;4568 } else {4569 *out << Verbose(3) << "Result: Not equal." << endl;4570 return NULL;4571 }4458 int flag; 4459 double *Distances = NULL, *OtherDistances = NULL; 4460 Vector CenterOfGravity, OtherCenterOfGravity; 4461 size_t *PermMap = NULL, *OtherPermMap = NULL; 4462 int *PermutationMap = NULL; 4463 atom *Walker = NULL; 4464 bool result = true; // status of comparison 4465 4466 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4467 /// first count both their atoms and elements and update lists thereby ... 4468 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4469 CountAtoms(out); 4470 OtherMolecule->CountAtoms(out); 4471 CountElements(); 4472 OtherMolecule->CountElements(); 4473 4474 /// ... and compare: 4475 /// -# AtomCount 4476 if (result) { 4477 if (AtomCount != OtherMolecule->AtomCount) { 4478 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4479 result = false; 4480 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4481 } 4482 /// -# ElementCount 4483 if (result) { 4484 if (ElementCount != OtherMolecule->ElementCount) { 4485 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4486 result = false; 4487 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4488 } 4489 /// -# ElementsInMolecule 4490 if (result) { 4491 for (flag=MAX_ELEMENTS;flag--;) { 4492 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4493 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4494 break; 4495 } 4496 if (flag < MAX_ELEMENTS) { 4497 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4498 result = false; 4499 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4500 } 4501 /// then determine and compare center of gravity for each molecule ... 4502 if (result) { 4503 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4504 DeterminePeriodicCenter(CenterOfGravity); 4505 OtherMolecule->DeterminePeriodicCenter(OtherCenterOfGravity); 4506 *out << Verbose(5) << "Center of Gravity: "; 4507 CenterOfGravity.Output(out); 4508 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4509 OtherCenterOfGravity.Output(out); 4510 *out << endl; 4511 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4512 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4513 result = false; 4514 } 4515 } 4516 4517 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4518 if (result) { 4519 *out << Verbose(5) << "Calculating distances" << endl; 4520 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4521 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4522 Walker = start; 4523 while (Walker->next != end) { 4524 Walker = Walker->next; 4525 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4526 } 4527 Walker = OtherMolecule->start; 4528 while (Walker->next != OtherMolecule->end) { 4529 Walker = Walker->next; 4530 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4531 } 4532 4533 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4534 *out << Verbose(5) << "Sorting distances" << endl; 4535 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4536 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4537 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4538 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4539 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4540 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4541 for(int i=AtomCount;i--;) 4542 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4543 4544 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4545 *out << Verbose(4) << "Comparing distances" << endl; 4546 flag = 0; 4547 for (int i=0;i<AtomCount;i++) { 4548 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4549 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4550 flag = 1; 4551 } 4552 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4553 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4554 4555 /// free memory 4556 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4557 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4558 if (flag) { // if not equal 4559 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4560 result = false; 4561 } 4562 } 4563 /// return pointer to map if all distances were below \a threshold 4564 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4565 if (result) { 4566 *out << Verbose(3) << "Result: Equal." << endl; 4567 return PermutationMap; 4568 } else { 4569 *out << Verbose(3) << "Result: Not equal." << endl; 4570 return NULL; 4571 } 4572 4572 }; 4573 4573 … … 4581 4581 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4582 4582 { 4583 atom *Walker = NULL, *OtherWalker = NULL;4584 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;4585 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4586 for (int i=AtomCount;i--;)4587 AtomicMap[i] = -1;4588 if (OtherMolecule == this) {// same molecule4589 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence4590 AtomicMap[i] = i;4591 *out << Verbose(4) << "Map is trivial." << endl;4592 } else {4593 *out << Verbose(4) << "Map is ";4594 Walker = start;4595 while (Walker->next != end) {4596 Walker = Walker->next;4597 if (Walker->father == NULL) {4598 AtomicMap[Walker->nr] = -2;4599 } else {4600 OtherWalker = OtherMolecule->start;4601 while (OtherWalker->next != OtherMolecule->end) {4602 OtherWalker = OtherWalker->next;4603 //for (int i=0;i<AtomCount;i++) { // search atom4604 //for (int j=0;j<OtherMolecule->AtomCount;j++) {4605 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;4606 if (Walker->father == OtherWalker)4607 AtomicMap[Walker->nr] = OtherWalker->nr;4608 }4609 }4610 *out << AtomicMap[Walker->nr] << "\t";4611 }4612 *out << endl;4613 }4614 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;4615 return AtomicMap;4583 atom *Walker = NULL, *OtherWalker = NULL; 4584 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4585 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4586 for (int i=AtomCount;i--;) 4587 AtomicMap[i] = -1; 4588 if (OtherMolecule == this) { // same molecule 4589 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4590 AtomicMap[i] = i; 4591 *out << Verbose(4) << "Map is trivial." << endl; 4592 } else { 4593 *out << Verbose(4) << "Map is "; 4594 Walker = start; 4595 while (Walker->next != end) { 4596 Walker = Walker->next; 4597 if (Walker->father == NULL) { 4598 AtomicMap[Walker->nr] = -2; 4599 } else { 4600 OtherWalker = OtherMolecule->start; 4601 while (OtherWalker->next != OtherMolecule->end) { 4602 OtherWalker = OtherWalker->next; 4603 //for (int i=0;i<AtomCount;i++) { // search atom 4604 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4605 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4606 if (Walker->father == OtherWalker) 4607 AtomicMap[Walker->nr] = OtherWalker->nr; 4608 } 4609 } 4610 *out << AtomicMap[Walker->nr] << "\t"; 4611 } 4612 *out << endl; 4613 } 4614 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4615 return AtomicMap; 4616 4616 }; 4617 4617 … … 4627 4627 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4628 4628 { 4629 double temperature;4630 atom *Walker = NULL;4631 // test stream4632 if (output == NULL)4633 return false;4634 else4635 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;4636 for (int step=startstep;step < endstep; step++) { // loop over all time steps4637 temperature = 0.;4638 Walker = start;4639 while (Walker->next != end) {4640 Walker = Walker->next;4641 for (int i=NDIM;i--;)4642 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];4643 }4644 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;4645 }4646 return true;4647 }; 4629 double temperature; 4630 atom *Walker = NULL; 4631 // test stream 4632 if (output == NULL) 4633 return false; 4634 else 4635 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4636 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4637 temperature = 0.; 4638 Walker = start; 4639 while (Walker->next != end) { 4640 Walker = Walker->next; 4641 for (int i=NDIM;i--;) 4642 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4643 } 4644 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4645 } 4646 return true; 4647 };
Note:
See TracChangeset
for help on using the changeset viewer.
