Changeset 042f82 for src/molecules.cpp
- Timestamp:
- Jul 23, 2009, 2:21:57 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, Candidate_v1.7.0, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- 36ec71
- Parents:
- 205ccd
- File:
-
- 1 edited
-
src/molecules.cpp (modified) (96 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/molecules.cpp
r205ccd r042f82 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");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 65 }; 66 66 … … 70 70 molecule::~molecule() 71 71 { 72 if (ListOfBondsPerAtom != NULL)73 for(int i=AtomCount;i--;)74 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]");75 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom");76 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom");77 CleanupMolecule();78 delete(first);79 delete(last);80 delete(end);81 delete(start);72 if (ListOfBondsPerAtom != NULL) 73 for(int i=AtomCount;i--;) 74 Free((void **)&ListOfBondsPerAtom[i], "molecule::~molecule: ListOfBondsPerAtom[i]"); 75 Free((void **)&ListOfBondsPerAtom, "molecule::~molecule: ListOfBondsPerAtom"); 76 Free((void **)&NumberOfBondsPerAtom, "molecule::~molecule: NumberOfBondsPerAtom"); 77 CleanupMolecule(); 78 delete(first); 79 delete(last); 80 delete(end); 81 delete(start); 82 82 }; 83 83 … … 89 89 bool molecule::AddAtom(atom *pointer) 90 90 { 91 if (pointer != NULL) {92 pointer->sort = &pointer->nr;93 pointer->nr = last_atom++;// increase number within molecule94 AtomCount++;95 if (pointer->type != NULL) {96 if (ElementsInMolecule[pointer->type->Z] == 0)97 ElementCount++;98 ElementsInMolecule[pointer->type->Z]++; // increase number of elements99 if (pointer->type->Z != 1)100 NoNonHydrogen++;101 if (pointer->Name == NULL) {102 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name");103 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name");104 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1);105 }106 }107 return add(pointer, end);108 } else109 return false;91 if (pointer != NULL) { 92 pointer->sort = &pointer->nr; 93 pointer->nr = last_atom++; // increase number within molecule 94 AtomCount++; 95 if (pointer->type != NULL) { 96 if (ElementsInMolecule[pointer->type->Z] == 0) 97 ElementCount++; 98 ElementsInMolecule[pointer->type->Z]++; // increase number of elements 99 if (pointer->type->Z != 1) 100 NoNonHydrogen++; 101 if (pointer->Name == NULL) { 102 Free((void **)&pointer->Name, "molecule::AddAtom: *pointer->Name"); 103 pointer->Name = (char *) Malloc(sizeof(char)*6, "molecule::AddAtom: *pointer->Name"); 104 sprintf(pointer->Name, "%2s%02d", pointer->type->symbol, pointer->nr+1); 105 } 106 } 107 return add(pointer, end); 108 } else 109 return false; 110 110 }; 111 111 … … 117 117 atom * molecule::AddCopyAtom(atom *pointer) 118 118 { 119 if (pointer != NULL) {120 atom *walker = new atom();121 walker->type = pointer->type;// copy element of atom122 walker->x.CopyVector(&pointer->x); // copy coordination123 walker->v.CopyVector(&pointer->v); // copy velocity124 walker->FixedIon = pointer->FixedIon;125 walker->sort = &walker->nr;126 walker->nr = last_atom++;// increase number within molecule127 walker->father = pointer; //->GetTrueFather();128 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name");129 strcpy (walker->Name, pointer->Name);130 add(walker, end);131 if ((pointer->type != NULL) && (pointer->type->Z != 1))132 NoNonHydrogen++;133 AtomCount++;134 return walker;135 } else136 return NULL;119 if (pointer != NULL) { 120 atom *walker = new atom(); 121 walker->type = pointer->type; // copy element of atom 122 walker->x.CopyVector(&pointer->x); // copy coordination 123 walker->v.CopyVector(&pointer->v); // copy velocity 124 walker->FixedIon = pointer->FixedIon; 125 walker->sort = &walker->nr; 126 walker->nr = last_atom++; // increase number within molecule 127 walker->father = pointer; //->GetTrueFather(); 128 walker->Name = (char *) Malloc(sizeof(char)*strlen(pointer->Name)+1, "molecule::AddCopyAtom: *Name"); 129 strcpy (walker->Name, pointer->Name); 130 add(walker, end); 131 if ((pointer->type != NULL) && (pointer->type->Z != 1)) 132 NoNonHydrogen++; 133 AtomCount++; 134 return walker; 135 } else 136 return NULL; 137 137 }; 138 138 … … 142 142 * -# Single Bond: Simply add new atom with bond distance rescaled to typical hydrogen one 143 143 * -# Double Bond: Here, we need the **BondList of the \a *origin atom, by scanning for the other bonds instead of 144 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector().145 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two146 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the147 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two148 * hydrogens forming this angle with *origin.144 * *Bond, we use the through these connected atoms to determine the plane they lie in, vector::MakeNormalvector(). 145 * The orthonormal vector to this plane along with the vector in *Bond direction determines the plane the two 146 * replacing hydrogens shall lie in. Now, all remains to do is take the usual hydrogen double bond angle for the 147 * element of *origin and form the sin/cos admixture of both plane vectors for the new coordinates of the two 148 * hydrogens forming this angle with *origin. 149 149 * -# 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 150 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be151 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin):152 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2).153 * \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 )}}154 * \f]155 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates156 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above.157 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that158 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1.159 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2}160 * \f]161 * as the coordination of all three atoms in the coordinate system of these three vectors:162 * \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$.150 * triangle formed by the to be added hydrogens are not equal to the typical bond distance \f$l\f$ but have to be 151 * determined from the typical angle \f$\alpha\f$ for a hydrogen triple connected to the element of *origin): 152 * We have the height \f$d\f$ as the vector in *Bond direction (from triangle C1-H1-H2). 153 * \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 )}} 154 * \f] 155 * vector::GetNormalvector() creates one orthonormal vector from this *Bond vector and vector::MakeNormalvector creates 156 * the third one from the former two vectors. The latter ones form the plane of the base triangle mentioned above. 157 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 158 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 159 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 160 * \f] 161 * as the coordination of all three atoms in the coordinate system of these three vectors: 162 * \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$. 163 163 * 164 164 * \param *out output stream for debugging … … 168 168 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule 169 169 * \param **BondList list of bonds \a *replacement has (necessary to determine plane for double and triple bonds) 170 * \param NumBond number of bonds in \a **BondList170 * \param NumBond number of bonds in \a **BondList 171 171 * \param isAngstroem whether the coordination of the given atoms is in AtomicLength (false) or Angstrom(true) 172 172 * \return number of atoms added, if < bond::BondDegree then something went wrong … … 175 175 bool molecule::AddHydrogenReplacementAtom(ofstream *out, bond *TopBond, atom *BottomOrigin, atom *TopOrigin, atom *TopReplacement, bond **BondList, int NumBond, bool IsAngstroem) 176 176 { 177 double bondlength;// bond length of the bond to be replaced/cut178 double bondangle;// bond angle of the bond to be replaced/cut179 double BondRescale;// rescale value for the hydrogen bond length180 bool AllWentWell = true;// flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit181 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane182 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added183 double b,l,d,f,g, alpha, factors[NDIM];// hold temporary values in triple bond case for coordination determination184 Vector Orthovector1, Orthovector2;// temporary vectors in coordination construction185 Vector InBondvector;// vector in direction of *Bond186 bond *Binder = NULL;187 double *matrix;188 189 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl;190 // create vector in direction of bond191 InBondvector.CopyVector(&TopReplacement->x);192 InBondvector.SubtractVector(&TopOrigin->x);193 bondlength = InBondvector.Norm();194 195 // is greater than typical bond distance? Then we have to correct periodically196 // the problem is not the H being out of the box, but InBondvector have the wrong direction197 // due to TopReplacement or Origin being on the wrong side!198 if (bondlength > BondDistance) {199 // *out << Verbose(4) << "InBondvector is: ";200 // InBondvector.Output(out);201 // *out << endl;202 Orthovector1.Zero();203 for (int i=NDIM;i--;) {204 l = TopReplacement->x.x[i] - TopOrigin->x.x[i];205 if (fabs(l) > BondDistance) { // is component greater than bond distance206 Orthovector1.x[i] = (l < 0) ? -1. : +1.;207 } // (signs are correct, was tested!)208 }209 matrix = ReturnFullMatrixforSymmetric(cell_size);210 Orthovector1.MatrixMultiplication(matrix);211 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation212 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix");213 bondlength = InBondvector.Norm();214 // *out << Verbose(4) << "Corrected InBondvector is now: ";215 // InBondvector.Output(out);216 // *out << endl;217 } // periodic correction finished218 219 InBondvector.Normalize();220 // get typical bond length and store as scale factor for later221 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1];222 if (BondRescale == -1) {223 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;224 return false;225 BondRescale = bondlength;226 } else {227 if (!IsAngstroem)228 BondRescale /= (1.*AtomicLengthToAngstroem);229 }230 231 // discern single, double and triple bonds232 switch(TopBond->BondDegree) {233 case 1:234 FirstOtherAtom = new atom();// new atom235 FirstOtherAtom->type = elemente->FindElement(1);// element is Hydrogen236 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity237 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;238 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen239 FirstOtherAtom->father = TopReplacement;240 BondRescale = bondlength;241 } else {242 FirstOtherAtom->father = NULL;// if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father243 }244 InBondvector.Scale(&BondRescale);// rescale the distance vector to Hydrogen bond length245 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ...246 FirstOtherAtom->x.AddVector(&InBondvector);// ... and add distance vector to replacement atom247 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);248 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";249 // FirstOtherAtom->x.Output(out);250 // *out << endl;251 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);252 Binder->Cyclic = false;253 Binder->Type = TreeEdge;254 break;255 case 2:256 // determine two other bonds (warning if there are more than two other) plus valence sanity check257 for (int i=0;i<NumBond;i++) {258 if (BondList[i] != TopBond) {259 if (FirstBond == NULL) {260 FirstBond = BondList[i];261 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);262 } else if (SecondBond == NULL) {263 SecondBond = BondList[i];264 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin);265 } else {266 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name;267 }268 }269 }270 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)271 SecondBond = TopBond;272 SecondOtherAtom = TopReplacement;273 }274 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all275 // *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;276 277 // determine the plane of these two with the *origin278 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x);279 } else {280 Orthovector1.GetOneNormalVector(&InBondvector);281 }282 //*out << Verbose(3)<< "Orthovector1: ";283 //Orthovector1.Output(out);284 //*out << endl;285 // orthogonal vector and bond vector between origin and replacement form the new plane286 Orthovector1.MakeNormalVector(&InBondvector);287 Orthovector1.Normalize();288 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl;289 290 // create the two Hydrogens ...291 FirstOtherAtom = new atom();292 SecondOtherAtom = new atom();293 FirstOtherAtom->type = elemente->FindElement(1);294 SecondOtherAtom->type = elemente->FindElement(1);295 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity296 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;297 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity298 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;299 FirstOtherAtom->father = NULL;// we are just an added hydrogen with no father300 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father301 bondangle = TopOrigin->type->HBondAngle[1];302 if (bondangle == -1) {303 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl;304 return false;305 bondangle = 0;306 }307 bondangle *= M_PI/180./2.;308 // *out << Verbose(3) << "ReScaleCheck: InBondvector ";309 // InBondvector.Output(out);310 // *out << endl;311 // *out << Verbose(3) << "ReScaleCheck: Orthovector ";312 // Orthovector1.Output(out);313 // *out << endl;314 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl;315 FirstOtherAtom->x.Zero();316 SecondOtherAtom->x.Zero();317 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction)318 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle));319 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle));320 }321 FirstOtherAtom->x.Scale(&BondRescale);// rescale by correct BondDistance322 SecondOtherAtom->x.Scale(&BondRescale);323 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;324 for(int i=NDIM;i--;) { // and make relative to origin atom325 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];326 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];327 }328 // ... and add to molecule329 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);330 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);331 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";332 // FirstOtherAtom->x.Output(out);333 // *out << endl;334 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";335 // SecondOtherAtom->x.Output(out);336 // *out << endl;337 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);338 Binder->Cyclic = false;339 Binder->Type = TreeEdge;340 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);341 Binder->Cyclic = false;342 Binder->Type = TreeEdge;343 break;344 case 3:345 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid)346 FirstOtherAtom = new atom();347 SecondOtherAtom = new atom();348 ThirdOtherAtom = new atom();349 FirstOtherAtom->type = elemente->FindElement(1);350 SecondOtherAtom->type = elemente->FindElement(1);351 ThirdOtherAtom->type = elemente->FindElement(1);352 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity353 FirstOtherAtom->FixedIon = TopReplacement->FixedIon;354 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity355 SecondOtherAtom->FixedIon = TopReplacement->FixedIon;356 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity357 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon;358 FirstOtherAtom->father = NULL; //we are just an added hydrogen with no father359 SecondOtherAtom->father = NULL; //we are just an added hydrogen with no father360 ThirdOtherAtom->father = NULL; //we are just an added hydrogen with no father361 362 // we need to vectors orthonormal the InBondvector363 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector);364 // *out << Verbose(3) << "Orthovector1: ";365 // Orthovector1.Output(out);366 // *out << endl;367 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1);368 // *out << Verbose(3) << "Orthovector2: ";369 // Orthovector2.Output(out);370 // *out << endl;371 372 // create correct coordination for the three atoms373 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.;// retrieve triple bond angle from database374 l = BondRescale;// desired bond length375 b = 2.*l*sin(alpha);// base length of isosceles triangle376 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.);// length for InBondvector377 f = b/sqrt(3.);// length for Orthvector1378 g = b/2.;// length for Orthvector2379 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl;380 // *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;381 factors[0] = d;382 factors[1] = f;383 factors[2] = 0.;384 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);385 factors[1] = -0.5*f;386 factors[2] = g;387 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);388 factors[2] = -g;389 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors);390 391 // rescale each to correct BondDistance392 // FirstOtherAtom->x.Scale(&BondRescale);393 // SecondOtherAtom->x.Scale(&BondRescale);394 // ThirdOtherAtom->x.Scale(&BondRescale);395 396 // and relative to *origin atom397 FirstOtherAtom->x.AddVector(&TopOrigin->x);398 SecondOtherAtom->x.AddVector(&TopOrigin->x);399 ThirdOtherAtom->x.AddVector(&TopOrigin->x);400 401 // ... and add to molecule402 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom);403 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom);404 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom);405 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: ";406 // FirstOtherAtom->x.Output(out);407 // *out << endl;408 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: ";409 // SecondOtherAtom->x.Output(out);410 // *out << endl;411 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: ";412 // ThirdOtherAtom->x.Output(out);413 // *out << endl;414 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1);415 Binder->Cyclic = false;416 Binder->Type = TreeEdge;417 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1);418 Binder->Cyclic = false;419 Binder->Type = TreeEdge;420 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1);421 Binder->Cyclic = false;422 Binder->Type = TreeEdge;423 break;424 default:425 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl;426 AllWentWell = false;427 break;428 }429 430 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl;431 return AllWentWell;177 double bondlength; // bond length of the bond to be replaced/cut 178 double bondangle; // bond angle of the bond to be replaced/cut 179 double BondRescale; // rescale value for the hydrogen bond length 180 bool AllWentWell = true; // flag gathering the boolean return value of molecule::AddAtom and other functions, as return value on exit 181 bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane 182 atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added 183 double b,l,d,f,g, alpha, factors[NDIM]; // hold temporary values in triple bond case for coordination determination 184 Vector Orthovector1, Orthovector2; // temporary vectors in coordination construction 185 Vector InBondvector; // vector in direction of *Bond 186 bond *Binder = NULL; 187 double *matrix; 188 189 // *out << Verbose(3) << "Begin of AddHydrogenReplacementAtom." << endl; 190 // create vector in direction of bond 191 InBondvector.CopyVector(&TopReplacement->x); 192 InBondvector.SubtractVector(&TopOrigin->x); 193 bondlength = InBondvector.Norm(); 194 195 // is greater than typical bond distance? Then we have to correct periodically 196 // the problem is not the H being out of the box, but InBondvector have the wrong direction 197 // due to TopReplacement or Origin being on the wrong side! 198 if (bondlength > BondDistance) { 199 // *out << Verbose(4) << "InBondvector is: "; 200 // InBondvector.Output(out); 201 // *out << endl; 202 Orthovector1.Zero(); 203 for (int i=NDIM;i--;) { 204 l = TopReplacement->x.x[i] - TopOrigin->x.x[i]; 205 if (fabs(l) > BondDistance) { // is component greater than bond distance 206 Orthovector1.x[i] = (l < 0) ? -1. : +1.; 207 } // (signs are correct, was tested!) 208 } 209 matrix = ReturnFullMatrixforSymmetric(cell_size); 210 Orthovector1.MatrixMultiplication(matrix); 211 InBondvector.SubtractVector(&Orthovector1); // subtract just the additional translation 212 Free((void **)&matrix, "molecule::AddHydrogenReplacementAtom: *matrix"); 213 bondlength = InBondvector.Norm(); 214 // *out << Verbose(4) << "Corrected InBondvector is now: "; 215 // InBondvector.Output(out); 216 // *out << endl; 217 } // periodic correction finished 218 219 InBondvector.Normalize(); 220 // get typical bond length and store as scale factor for later 221 BondRescale = TopOrigin->type->HBondDistance[TopBond->BondDegree-1]; 222 if (BondRescale == -1) { 223 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 224 return false; 225 BondRescale = bondlength; 226 } else { 227 if (!IsAngstroem) 228 BondRescale /= (1.*AtomicLengthToAngstroem); 229 } 230 231 // discern single, double and triple bonds 232 switch(TopBond->BondDegree) { 233 case 1: 234 FirstOtherAtom = new atom(); // new atom 235 FirstOtherAtom->type = elemente->FindElement(1); // element is Hydrogen 236 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 237 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 238 if (TopReplacement->type->Z == 1) { // neither rescale nor replace if it's already hydrogen 239 FirstOtherAtom->father = TopReplacement; 240 BondRescale = bondlength; 241 } else { 242 FirstOtherAtom->father = NULL; // if we replace hydrogen, we mark it as our father, otherwise we are just an added hydrogen with no father 243 } 244 InBondvector.Scale(&BondRescale); // rescale the distance vector to Hydrogen bond length 245 FirstOtherAtom->x.CopyVector(&TopOrigin->x); // set coordination to origin ... 246 FirstOtherAtom->x.AddVector(&InBondvector); // ... and add distance vector to replacement atom 247 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 248 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 249 // FirstOtherAtom->x.Output(out); 250 // *out << endl; 251 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 252 Binder->Cyclic = false; 253 Binder->Type = TreeEdge; 254 break; 255 case 2: 256 // determine two other bonds (warning if there are more than two other) plus valence sanity check 257 for (int i=0;i<NumBond;i++) { 258 if (BondList[i] != TopBond) { 259 if (FirstBond == NULL) { 260 FirstBond = BondList[i]; 261 FirstOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 262 } else if (SecondBond == NULL) { 263 SecondBond = BondList[i]; 264 SecondOtherAtom = BondList[i]->GetOtherAtom(TopOrigin); 265 } else { 266 *out << Verbose(3) << "WARNING: Detected more than four bonds for atom " << TopOrigin->Name; 267 } 268 } 269 } 270 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) 271 SecondBond = TopBond; 272 SecondOtherAtom = TopReplacement; 273 } 274 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 275 // *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; 276 277 // determine the plane of these two with the *origin 278 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); 279 } else { 280 Orthovector1.GetOneNormalVector(&InBondvector); 281 } 282 //*out << Verbose(3)<< "Orthovector1: "; 283 //Orthovector1.Output(out); 284 //*out << endl; 285 // orthogonal vector and bond vector between origin and replacement form the new plane 286 Orthovector1.MakeNormalVector(&InBondvector); 287 Orthovector1.Normalize(); 288 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 289 290 // create the two Hydrogens ... 291 FirstOtherAtom = new atom(); 292 SecondOtherAtom = new atom(); 293 FirstOtherAtom->type = elemente->FindElement(1); 294 SecondOtherAtom->type = elemente->FindElement(1); 295 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 296 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 297 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 298 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 299 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 300 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 301 bondangle = TopOrigin->type->HBondAngle[1]; 302 if (bondangle == -1) { 303 *out << Verbose(3) << "ERROR: There is no typical hydrogen bond angle in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 304 return false; 305 bondangle = 0; 306 } 307 bondangle *= M_PI/180./2.; 308 // *out << Verbose(3) << "ReScaleCheck: InBondvector "; 309 // InBondvector.Output(out); 310 // *out << endl; 311 // *out << Verbose(3) << "ReScaleCheck: Orthovector "; 312 // Orthovector1.Output(out); 313 // *out << endl; 314 // *out << Verbose(3) << "Half the bond angle is " << bondangle << ", sin and cos of it: " << sin(bondangle) << ", " << cos(bondangle) << endl; 315 FirstOtherAtom->x.Zero(); 316 SecondOtherAtom->x.Zero(); 317 for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondvector is bondangle = 0 direction) 318 FirstOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (sin(bondangle)); 319 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 320 } 321 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 322 SecondOtherAtom->x.Scale(&BondRescale); 323 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 324 for(int i=NDIM;i--;) { // and make relative to origin atom 325 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 327 } 328 // ... and add to molecule 329 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 330 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 331 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 332 // FirstOtherAtom->x.Output(out); 333 // *out << endl; 334 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 335 // SecondOtherAtom->x.Output(out); 336 // *out << endl; 337 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 338 Binder->Cyclic = false; 339 Binder->Type = TreeEdge; 340 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 341 Binder->Cyclic = false; 342 Binder->Type = TreeEdge; 343 break; 344 case 3: 345 // take the "usual" tetraoidal angle and add the three Hydrogen in direction of the bond (height of the tetraoid) 346 FirstOtherAtom = new atom(); 347 SecondOtherAtom = new atom(); 348 ThirdOtherAtom = new atom(); 349 FirstOtherAtom->type = elemente->FindElement(1); 350 SecondOtherAtom->type = elemente->FindElement(1); 351 ThirdOtherAtom->type = elemente->FindElement(1); 352 FirstOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 353 FirstOtherAtom->FixedIon = TopReplacement->FixedIon; 354 SecondOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 355 SecondOtherAtom->FixedIon = TopReplacement->FixedIon; 356 ThirdOtherAtom->v.CopyVector(&TopReplacement->v); // copy velocity 357 ThirdOtherAtom->FixedIon = TopReplacement->FixedIon; 358 FirstOtherAtom->father = NULL; // we are just an added hydrogen with no father 359 SecondOtherAtom->father = NULL; // we are just an added hydrogen with no father 360 ThirdOtherAtom->father = NULL; // we are just an added hydrogen with no father 361 362 // we need to vectors orthonormal the InBondvector 363 AllWentWell = AllWentWell && Orthovector1.GetOneNormalVector(&InBondvector); 364 // *out << Verbose(3) << "Orthovector1: "; 365 // Orthovector1.Output(out); 366 // *out << endl; 367 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 368 // *out << Verbose(3) << "Orthovector2: "; 369 // Orthovector2.Output(out); 370 // *out << endl; 371 372 // create correct coordination for the three atoms 373 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database 374 l = BondRescale; // desired bond length 375 b = 2.*l*sin(alpha); // base length of isosceles triangle 376 d = l*sqrt(cos(alpha)*cos(alpha) - sin(alpha)*sin(alpha)/3.); // length for InBondvector 377 f = b/sqrt(3.); // length for Orthvector1 378 g = b/2.; // length for Orthvector2 379 // *out << Verbose(3) << "Bond length and half-angle: " << l << ", " << alpha << "\t (b,d,f,g) = " << b << ", " << d << ", " << f << ", " << g << ", " << endl; 380 // *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; 381 factors[0] = d; 382 factors[1] = f; 383 factors[2] = 0.; 384 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 385 factors[1] = -0.5*f; 386 factors[2] = g; 387 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 388 factors[2] = -g; 389 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 390 391 // rescale each to correct BondDistance 392 // FirstOtherAtom->x.Scale(&BondRescale); 393 // SecondOtherAtom->x.Scale(&BondRescale); 394 // ThirdOtherAtom->x.Scale(&BondRescale); 395 396 // and relative to *origin atom 397 FirstOtherAtom->x.AddVector(&TopOrigin->x); 398 SecondOtherAtom->x.AddVector(&TopOrigin->x); 399 ThirdOtherAtom->x.AddVector(&TopOrigin->x); 400 401 // ... and add to molecule 402 AllWentWell = AllWentWell && AddAtom(FirstOtherAtom); 403 AllWentWell = AllWentWell && AddAtom(SecondOtherAtom); 404 AllWentWell = AllWentWell && AddAtom(ThirdOtherAtom); 405 // *out << Verbose(4) << "Added " << *FirstOtherAtom << " at: "; 406 // FirstOtherAtom->x.Output(out); 407 // *out << endl; 408 // *out << Verbose(4) << "Added " << *SecondOtherAtom << " at: "; 409 // SecondOtherAtom->x.Output(out); 410 // *out << endl; 411 // *out << Verbose(4) << "Added " << *ThirdOtherAtom << " at: "; 412 // ThirdOtherAtom->x.Output(out); 413 // *out << endl; 414 Binder = AddBond(BottomOrigin, FirstOtherAtom, 1); 415 Binder->Cyclic = false; 416 Binder->Type = TreeEdge; 417 Binder = AddBond(BottomOrigin, SecondOtherAtom, 1); 418 Binder->Cyclic = false; 419 Binder->Type = TreeEdge; 420 Binder = AddBond(BottomOrigin, ThirdOtherAtom, 1); 421 Binder->Cyclic = false; 422 Binder->Type = TreeEdge; 423 break; 424 default: 425 cerr << "ERROR: BondDegree does not state single, double or triple bond!" << endl; 426 AllWentWell = false; 427 break; 428 } 429 430 // *out << Verbose(3) << "End of AddHydrogenReplacementAtom." << endl; 431 return AllWentWell; 432 432 }; 433 433 … … 439 439 bool molecule::AddXYZFile(string filename) 440 440 { 441 istringstream *input = NULL;442 int NumberOfAtoms = 0; // atom number in xyz read443 int i, j; // loop variables444 atom *Walker = NULL;// pointer to added atom445 char shorthand[3];// shorthand for atom name446 ifstream xyzfile;// xyz file447 string line;// currently parsed line448 double x[3];// atom coordinates449 450 xyzfile.open(filename.c_str());451 if (!xyzfile)452 return false;453 454 getline(xyzfile,line,'\n'); // Read numer of atoms in file455 input = new istringstream(line);456 *input >> NumberOfAtoms;457 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl;458 getline(xyzfile,line,'\n'); // Read comment459 cout << Verbose(1) << "Comment: " << line << endl;460 461 if (MDSteps == 0) // no atoms yet present462 MDSteps++;463 for(i=0;i<NumberOfAtoms;i++){464 Walker = new atom;465 getline(xyzfile,line,'\n');466 istringstream *item = new istringstream(line);467 //istringstream input(line);468 //cout << Verbose(1) << "Reading: " << line << endl;469 *item >> shorthand;470 *item >> x[0];471 *item >> x[1];472 *item >> x[2];473 Walker->type = elemente->FindElement(shorthand);474 if (Walker->type == NULL) {475 cerr << "Could not parse the element at line: '" << line << "', setting to H.";476 Walker->type = elemente->FindElement(1);477 }478 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) {479 Trajectories[Walker].R.resize(MDSteps+10);480 Trajectories[Walker].U.resize(MDSteps+10);481 Trajectories[Walker].F.resize(MDSteps+10);482 }483 for(j=NDIM;j--;) {484 Walker->x.x[j] = x[j];485 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j];486 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0;487 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0;488 }489 AddAtom(Walker);// add to molecule490 delete(item);491 }492 xyzfile.close();493 delete(input);494 return true;441 istringstream *input = NULL; 442 int NumberOfAtoms = 0; // atom number in xyz read 443 int i, j; // loop variables 444 atom *Walker = NULL; // pointer to added atom 445 char shorthand[3]; // shorthand for atom name 446 ifstream xyzfile; // xyz file 447 string line; // currently parsed line 448 double x[3]; // atom coordinates 449 450 xyzfile.open(filename.c_str()); 451 if (!xyzfile) 452 return false; 453 454 getline(xyzfile,line,'\n'); // Read numer of atoms in file 455 input = new istringstream(line); 456 *input >> NumberOfAtoms; 457 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 458 getline(xyzfile,line,'\n'); // Read comment 459 cout << Verbose(1) << "Comment: " << line << endl; 460 461 if (MDSteps == 0) // no atoms yet present 462 MDSteps++; 463 for(i=0;i<NumberOfAtoms;i++){ 464 Walker = new atom; 465 getline(xyzfile,line,'\n'); 466 istringstream *item = new istringstream(line); 467 //istringstream input(line); 468 //cout << Verbose(1) << "Reading: " << line << endl; 469 *item >> shorthand; 470 *item >> x[0]; 471 *item >> x[1]; 472 *item >> x[2]; 473 Walker->type = elemente->FindElement(shorthand); 474 if (Walker->type == NULL) { 475 cerr << "Could not parse the element at line: '" << line << "', setting to H."; 476 Walker->type = elemente->FindElement(1); 477 } 478 if (Trajectories[Walker].R.size() <= (unsigned int)MDSteps) { 479 Trajectories[Walker].R.resize(MDSteps+10); 480 Trajectories[Walker].U.resize(MDSteps+10); 481 Trajectories[Walker].F.resize(MDSteps+10); 482 } 483 for(j=NDIM;j--;) { 484 Walker->x.x[j] = x[j]; 485 Trajectories[Walker].R.at(MDSteps-1).x[j] = x[j]; 486 Trajectories[Walker].U.at(MDSteps-1).x[j] = 0; 487 Trajectories[Walker].F.at(MDSteps-1).x[j] = 0; 488 } 489 AddAtom(Walker); // add to molecule 490 delete(item); 491 } 492 xyzfile.close(); 493 delete(input); 494 return true; 495 495 }; 496 496 … … 500 500 molecule *molecule::CopyMolecule() 501 501 { 502 molecule *copy = new molecule(elemente);503 atom *CurrentAtom = NULL;504 atom *LeftAtom = NULL, *RightAtom = NULL;505 atom *Walker = NULL;506 507 // copy all atoms508 Walker = start;509 while(Walker->next != end) {510 Walker = Walker->next;511 CurrentAtom = copy->AddCopyAtom(Walker);512 }513 514 // copy all bonds515 bond *Binder = first;516 bond *NewBond = NULL;517 while(Binder->next != last) {518 Binder = Binder->next;519 // get the pendant atoms of current bond in the copy molecule520 LeftAtom = copy->start;521 while (LeftAtom->next != copy->end) {522 LeftAtom = LeftAtom->next;523 if (LeftAtom->father == Binder->leftatom)524 break;525 }526 RightAtom = copy->start;527 while (RightAtom->next != copy->end) {528 RightAtom = RightAtom->next;529 if (RightAtom->father == Binder->rightatom)530 break;531 }532 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree);533 NewBond->Cyclic = Binder->Cyclic;534 if (Binder->Cyclic)535 copy->NoCyclicBonds++;536 NewBond->Type = Binder->Type;537 }538 // correct fathers539 Walker = copy->start;540 while(Walker->next != copy->end) {541 Walker = Walker->next;542 if (Walker->father->father == Walker->father)// same atom in copy's father points to itself543 Walker->father = Walker;// set father to itself (copy of a whole molecule)544 else545 Walker->father = Walker->father->father;// set father to original's father546 }547 // copy values548 copy->CountAtoms((ofstream *)&cout);549 copy->CountElements();550 if (first->next != last) {// if adjaceny list is present551 copy->BondDistance = BondDistance;552 copy->CreateListOfBondsPerAtom((ofstream *)&cout);553 }554 555 return copy;502 molecule *copy = new molecule(elemente); 503 atom *CurrentAtom = NULL; 504 atom *LeftAtom = NULL, *RightAtom = NULL; 505 atom *Walker = NULL; 506 507 // copy all atoms 508 Walker = start; 509 while(Walker->next != end) { 510 Walker = Walker->next; 511 CurrentAtom = copy->AddCopyAtom(Walker); 512 } 513 514 // copy all bonds 515 bond *Binder = first; 516 bond *NewBond = NULL; 517 while(Binder->next != last) { 518 Binder = Binder->next; 519 // get the pendant atoms of current bond in the copy molecule 520 LeftAtom = copy->start; 521 while (LeftAtom->next != copy->end) { 522 LeftAtom = LeftAtom->next; 523 if (LeftAtom->father == Binder->leftatom) 524 break; 525 } 526 RightAtom = copy->start; 527 while (RightAtom->next != copy->end) { 528 RightAtom = RightAtom->next; 529 if (RightAtom->father == Binder->rightatom) 530 break; 531 } 532 NewBond = copy->AddBond(LeftAtom, RightAtom, Binder->BondDegree); 533 NewBond->Cyclic = Binder->Cyclic; 534 if (Binder->Cyclic) 535 copy->NoCyclicBonds++; 536 NewBond->Type = Binder->Type; 537 } 538 // correct fathers 539 Walker = copy->start; 540 while(Walker->next != copy->end) { 541 Walker = Walker->next; 542 if (Walker->father->father == Walker->father) // same atom in copy's father points to itself 543 Walker->father = Walker; // set father to itself (copy of a whole molecule) 544 else 545 Walker->father = Walker->father->father; // set father to original's father 546 } 547 // copy values 548 copy->CountAtoms((ofstream *)&cout); 549 copy->CountElements(); 550 if (first->next != last) { // if adjaceny list is present 551 copy->BondDistance = BondDistance; 552 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 553 } 554 555 return copy; 556 556 }; 557 557 … … 564 564 bond * molecule::AddBond(atom *atom1, atom *atom2, int degree=1) 565 565 { 566 bond *Binder = NULL;567 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) {568 Binder = new bond(atom1, atom2, degree, BondCount++);569 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1))570 NoNonBonds++;571 add(Binder, last);572 } else {573 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;574 }575 return Binder;566 bond *Binder = NULL; 567 if ((atom1 != NULL) && (FindAtom(atom1->nr) != NULL) && (atom2 != NULL) && (FindAtom(atom2->nr) != NULL)) { 568 Binder = new bond(atom1, atom2, degree, BondCount++); 569 if ((atom1->type != NULL) && (atom1->type->Z != 1) && (atom2->type != NULL) && (atom2->type->Z != 1)) 570 NoNonBonds++; 571 add(Binder, last); 572 } else { 573 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; 574 } 575 return Binder; 576 576 }; 577 577 … … 583 583 bool molecule::RemoveBond(bond *pointer) 584 584 { 585 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;586 removewithoutcheck(pointer);587 return true;585 //cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 586 removewithoutcheck(pointer); 587 return true; 588 588 }; 589 589 … … 595 595 bool molecule::RemoveBonds(atom *BondPartner) 596 596 { 597 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl;598 return false;597 cerr << Verbose(1) << "molecule::RemoveBond: Function not implemented yet." << endl; 598 return false; 599 599 }; 600 600 … … 619 619 void molecule::SetBoxDimension(Vector *dim) 620 620 { 621 cell_size[0] = dim->x[0];622 cell_size[1] = 0.;623 cell_size[2] = dim->x[1];624 cell_size[3] = 0.;625 cell_size[4] = 0.;626 cell_size[5] = dim->x[2];621 cell_size[0] = dim->x[0]; 622 cell_size[1] = 0.; 623 cell_size[2] = dim->x[1]; 624 cell_size[3] = 0.; 625 cell_size[4] = 0.; 626 cell_size[5] = dim->x[2]; 627 627 }; 628 628 … … 632 632 bool molecule::CenterInBox(ofstream *out) 633 633 { 634 bool status = true;635 atom *ptr = NULL;636 Vector x;637 double *M = ReturnFullMatrixforSymmetric(cell_size);634 bool status = true; 635 atom *ptr = NULL; 636 Vector x; 637 double *M = ReturnFullMatrixforSymmetric(cell_size); 638 638 double *Minv = x.InverseMatrix(M); 639 double value;640 641 // cout << "The box matrix is :" << endl;639 double value; 640 641 // cout << "The box matrix is :" << endl; 642 642 // for (int i=0;i<NDIM;++i) { 643 643 // for (int j=0;j<NDIM;++j) … … 651 651 // cout << endl; 652 652 // } 653 // go through all atoms653 // go through all atoms 654 654 ptr = start->next; // start at first in list 655 655 if (ptr != end) { //list not empty? … … 676 676 delete(M); 677 677 delete(Minv); 678 return status;678 return status; 679 679 }; 680 680 … … 685 685 void molecule::CenterEdge(ofstream *out, Vector *max) 686 686 { 687 Vector *min = new Vector;688 689 // *out << Verbose(3) << "Begin of CenterEdge." << endl;690 atom *ptr = start->next;// start at first in list691 if (ptr != end) {//list not empty?692 for (int i=NDIM;i--;) {693 max->x[i] = ptr->x.x[i];694 min->x[i] = ptr->x.x[i];695 }696 while (ptr->next != end) {// continue with second if present697 ptr = ptr->next;698 //ptr->Output(1,1,out);699 for (int i=NDIM;i--;) {700 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i];701 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i];702 }703 }704 // *out << Verbose(4) << "Maximum is ";705 // max->Output(out);706 // *out << ", Minimum is ";707 // min->Output(out);708 // *out << endl;709 min->Scale(-1.);710 max->AddVector(min);711 Translate(min);712 }713 delete(min);714 // *out << Verbose(3) << "End of CenterEdge." << endl;687 Vector *min = new Vector; 688 689 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 690 atom *ptr = start->next; // start at first in list 691 if (ptr != end) { //list not empty? 692 for (int i=NDIM;i--;) { 693 max->x[i] = ptr->x.x[i]; 694 min->x[i] = ptr->x.x[i]; 695 } 696 while (ptr->next != end) { // continue with second if present 697 ptr = ptr->next; 698 //ptr->Output(1,1,out); 699 for (int i=NDIM;i--;) { 700 max->x[i] = (max->x[i] < ptr->x.x[i]) ? ptr->x.x[i] : max->x[i]; 701 min->x[i] = (min->x[i] > ptr->x.x[i]) ? ptr->x.x[i] : min->x[i]; 702 } 703 } 704 // *out << Verbose(4) << "Maximum is "; 705 // max->Output(out); 706 // *out << ", Minimum is "; 707 // min->Output(out); 708 // *out << endl; 709 min->Scale(-1.); 710 max->AddVector(min); 711 Translate(min); 712 } 713 delete(min); 714 // *out << Verbose(3) << "End of CenterEdge." << endl; 715 715 }; 716 716 … … 721 721 void molecule::CenterOrigin(ofstream *out, Vector *center) 722 722 { 723 int Num = 0;724 atom *ptr = start->next;// start at first in list725 726 for(int i=NDIM;i--;) // zero center vector727 center->x[i] = 0.;728 729 if (ptr != end) {//list not empty?730 while (ptr->next != end) {// continue with second if present731 ptr = ptr->next;732 Num++;733 center->AddVector(&ptr->x);734 }735 center->Scale(-1./Num); // divide through total number (and sign for direction)736 Translate(center);737 }723 int Num = 0; 724 atom *ptr = start->next; // start at first in list 725 726 for(int i=NDIM;i--;) // zero center vector 727 center->x[i] = 0.; 728 729 if (ptr != end) { //list not empty? 730 while (ptr->next != end) { // continue with second if present 731 ptr = ptr->next; 732 Num++; 733 center->AddVector(&ptr->x); 734 } 735 center->Scale(-1./Num); // divide through total number (and sign for direction) 736 Translate(center); 737 } 738 738 }; 739 739 … … 744 744 Vector * molecule::DetermineCenterOfAll(ofstream *out) 745 745 { 746 atom *ptr = start->next;// start at first in list747 Vector *a = new Vector();748 Vector tmp;749 double Num = 0;750 751 a->Zero();752 753 if (ptr != end) {//list not empty?754 while (ptr->next != end) {// continue with second if present755 ptr = ptr->next;756 Num += 1.;757 tmp.CopyVector(&ptr->x);758 a->AddVector(&tmp);759 }760 a->Scale(-1./Num); // divide through total mass (and sign for direction)761 }762 //cout << Verbose(1) << "Resulting center of gravity: ";763 //a->Output(out);764 //cout << endl;765 return a;746 atom *ptr = start->next; // start at first in list 747 Vector *a = new Vector(); 748 Vector tmp; 749 double Num = 0; 750 751 a->Zero(); 752 753 if (ptr != end) { //list not empty? 754 while (ptr->next != end) { // continue with second if present 755 ptr = ptr->next; 756 Num += 1.; 757 tmp.CopyVector(&ptr->x); 758 a->AddVector(&tmp); 759 } 760 a->Scale(-1./Num); // divide through total mass (and sign for direction) 761 } 762 //cout << Verbose(1) << "Resulting center of gravity: "; 763 //a->Output(out); 764 //cout << endl; 765 return a; 766 766 }; 767 767 … … 772 772 Vector * molecule::DetermineCenterOfGravity(ofstream *out) 773 773 { 774 atom *ptr = start->next;// start at first in list775 Vector *a = new Vector();776 Vector tmp;777 double Num = 0;778 779 a->Zero();780 781 if (ptr != end) {//list not empty?782 while (ptr->next != end) {// continue with second if present783 ptr = ptr->next;784 Num += ptr->type->mass;785 tmp.CopyVector(&ptr->x);786 tmp.Scale(ptr->type->mass);// scale by mass787 a->AddVector(&tmp);788 }789 a->Scale(-1./Num); // divide through total mass (and sign for direction)790 }791 // *out << Verbose(1) << "Resulting center of gravity: ";792 // a->Output(out);793 // *out << endl;794 return a;774 atom *ptr = start->next; // start at first in list 775 Vector *a = new Vector(); 776 Vector tmp; 777 double Num = 0; 778 779 a->Zero(); 780 781 if (ptr != end) { //list not empty? 782 while (ptr->next != end) { // continue with second if present 783 ptr = ptr->next; 784 Num += ptr->type->mass; 785 tmp.CopyVector(&ptr->x); 786 tmp.Scale(ptr->type->mass); // scale by mass 787 a->AddVector(&tmp); 788 } 789 a->Scale(-1./Num); // divide through total mass (and sign for direction) 790 } 791 // *out << Verbose(1) << "Resulting center of gravity: "; 792 // a->Output(out); 793 // *out << endl; 794 return a; 795 795 }; 796 796 … … 801 801 void molecule::CenterGravity(ofstream *out, Vector *center) 802 802 { 803 if (center == NULL) {804 DetermineCenter(*center);805 Translate(center);806 delete(center);807 } else {808 Translate(center);809 }803 if (center == NULL) { 804 DetermineCenter(*center); 805 Translate(center); 806 delete(center); 807 } else { 808 Translate(center); 809 } 810 810 }; 811 811 … … 815 815 void molecule::Scale(double **factor) 816 816 { 817 atom *ptr = start;818 819 while (ptr->next != end) {820 ptr = ptr->next;821 for (int j=0;j<MDSteps;j++)822 Trajectories[ptr].R.at(j).Scale(factor);823 ptr->x.Scale(factor);824 }817 atom *ptr = start; 818 819 while (ptr->next != end) { 820 ptr = ptr->next; 821 for (int j=0;j<MDSteps;j++) 822 Trajectories[ptr].R.at(j).Scale(factor); 823 ptr->x.Scale(factor); 824 } 825 825 }; 826 826 … … 830 830 void molecule::Translate(const Vector *trans) 831 831 { 832 atom *ptr = start;833 834 while (ptr->next != end) {835 ptr = ptr->next;836 for (int j=0;j<MDSteps;j++)837 Trajectories[ptr].R.at(j).Translate(trans);838 ptr->x.Translate(trans);839 }832 atom *ptr = start; 833 834 while (ptr->next != end) { 835 ptr = ptr->next; 836 for (int j=0;j<MDSteps;j++) 837 Trajectories[ptr].R.at(j).Translate(trans); 838 ptr->x.Translate(trans); 839 } 840 840 }; 841 841 … … 900 900 void molecule::Mirror(const Vector *n) 901 901 { 902 atom *ptr = start;903 904 while (ptr->next != end) {905 ptr = ptr->next;906 for (int j=0;j<MDSteps;j++)907 Trajectories[ptr].R.at(j).Mirror(n);908 ptr->x.Mirror(n);909 }902 atom *ptr = start; 903 904 while (ptr->next != end) { 905 ptr = ptr->next; 906 for (int j=0;j<MDSteps;j++) 907 Trajectories[ptr].R.at(j).Mirror(n); 908 ptr->x.Mirror(n); 909 } 910 910 }; 911 911 … … 915 915 void molecule::DetermineCenter(Vector &Center) 916 916 { 917 atom *Walker = start;918 bond *Binder = NULL;919 double *matrix = ReturnFullMatrixforSymmetric(cell_size);920 double tmp;921 bool flag;922 Vector Testvector, Translationvector;923 924 do {925 Center.Zero();926 flag = true;927 while (Walker->next != end) {928 Walker = Walker->next;917 atom *Walker = start; 918 bond *Binder = NULL; 919 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 920 double tmp; 921 bool flag; 922 Vector Testvector, Translationvector; 923 924 do { 925 Center.Zero(); 926 flag = true; 927 while (Walker->next != end) { 928 Walker = Walker->next; 929 929 #ifdef ADDHYDROGEN 930 if (Walker->type->Z != 1) {930 if (Walker->type->Z != 1) { 931 931 #endif 932 Testvector.CopyVector(&Walker->x);933 Testvector.InverseMatrixMultiplication(matrix);934 Translationvector.Zero();935 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {936 Binder = ListOfBondsPerAtom[Walker->nr][i];937 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing938 for (int j=0;j<NDIM;j++) {939 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j];940 if ((fabs(tmp)) > BondDistance) {941 flag = false;942 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl;943 if (tmp > 0)944 Translationvector.x[j] -= 1.;945 else946 Translationvector.x[j] += 1.;947 }948 }949 }950 Testvector.AddVector(&Translationvector);951 Testvector.MatrixMultiplication(matrix);952 Center.AddVector(&Testvector);953 cout << Verbose(1) << "vector is: ";954 Testvector.Output((ofstream *)&cout);955 cout << endl;932 Testvector.CopyVector(&Walker->x); 933 Testvector.InverseMatrixMultiplication(matrix); 934 Translationvector.Zero(); 935 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 936 Binder = ListOfBondsPerAtom[Walker->nr][i]; 937 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 938 for (int j=0;j<NDIM;j++) { 939 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 940 if ((fabs(tmp)) > BondDistance) { 941 flag = false; 942 cout << Verbose(0) << "Hit: atom " << Walker->Name << " in bond " << *Binder << " has to be shifted due to " << tmp << "." << endl; 943 if (tmp > 0) 944 Translationvector.x[j] -= 1.; 945 else 946 Translationvector.x[j] += 1.; 947 } 948 } 949 } 950 Testvector.AddVector(&Translationvector); 951 Testvector.MatrixMultiplication(matrix); 952 Center.AddVector(&Testvector); 953 cout << Verbose(1) << "vector is: "; 954 Testvector.Output((ofstream *)&cout); 955 cout << endl; 956 956 #ifdef ADDHYDROGEN 957 // now also change all hydrogens958 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {959 Binder = ListOfBondsPerAtom[Walker->nr][i];960 if (Binder->GetOtherAtom(Walker)->type->Z == 1) {961 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x);962 Testvector.InverseMatrixMultiplication(matrix);963 Testvector.AddVector(&Translationvector);964 Testvector.MatrixMultiplication(matrix);965 Center.AddVector(&Testvector);966 cout << Verbose(1) << "Hydrogen vector is: ";967 Testvector.Output((ofstream *)&cout);968 cout << endl;969 }970 }971 }957 // now also change all hydrogens 958 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 959 Binder = ListOfBondsPerAtom[Walker->nr][i]; 960 if (Binder->GetOtherAtom(Walker)->type->Z == 1) { 961 Testvector.CopyVector(&Binder->GetOtherAtom(Walker)->x); 962 Testvector.InverseMatrixMultiplication(matrix); 963 Testvector.AddVector(&Translationvector); 964 Testvector.MatrixMultiplication(matrix); 965 Center.AddVector(&Testvector); 966 cout << Verbose(1) << "Hydrogen vector is: "; 967 Testvector.Output((ofstream *)&cout); 968 cout << endl; 969 } 970 } 971 } 972 972 #endif 973 }974 } while (!flag);975 Free((void **)&matrix, "molecule::DetermineCenter: *matrix");976 Center.Scale(1./(double)AtomCount);973 } 974 } while (!flag); 975 Free((void **)&matrix, "molecule::DetermineCenter: *matrix"); 976 Center.Scale(1./(double)AtomCount); 977 977 }; 978 978 … … 983 983 void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate) 984 984 { 985 atom *ptr = start;// start at first in list986 double InertiaTensor[NDIM*NDIM];987 Vector *CenterOfGravity = DetermineCenterOfGravity(out);988 989 CenterGravity(out, CenterOfGravity);990 991 // reset inertia tensor992 for(int i=0;i<NDIM*NDIM;i++)993 InertiaTensor[i] = 0.;994 995 // sum up inertia tensor996 while (ptr->next != end) {997 ptr = ptr->next;998 Vector x;999 x.CopyVector(&ptr->x);1000 //x.SubtractVector(CenterOfGravity);1001 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);1002 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);1003 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);1004 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);1005 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);1006 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);1007 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);1008 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);1009 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);1010 }1011 // print InertiaTensor for debugging1012 *out << "The inertia tensor is:" << endl;1013 for(int i=0;i<NDIM;i++) {1014 for(int j=0;j<NDIM;j++)1015 *out << InertiaTensor[i*NDIM+j] << " ";1016 *out << endl;1017 }1018 *out << endl;1019 1020 // diagonalize to determine principal axis system1021 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);1022 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);1023 gsl_vector *eval = gsl_vector_alloc(NDIM);1024 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);1025 gsl_eigen_symmv(&m.matrix, eval, evec, T);1026 gsl_eigen_symmv_free(T);1027 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);1028 1029 for(int i=0;i<NDIM;i++) {1030 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);1031 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;1032 }1033 1034 // check whether we rotate or not1035 if (DoRotate) {1036 *out << Verbose(1) << "Transforming molecule into PAS ... ";1037 // the eigenvectors specify the transformation matrix1038 ptr = start;1039 while (ptr->next != end) {1040 ptr = ptr->next;1041 for (int j=0;j<MDSteps;j++)1042 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data);1043 ptr->x.MatrixMultiplication(evec->data);1044 }1045 *out << "done." << endl;1046 1047 // summing anew for debugging (resulting matrix has to be diagonal!)1048 // reset inertia tensor1049 for(int i=0;i<NDIM*NDIM;i++)1050 InertiaTensor[i] = 0.;1051 1052 // sum up inertia tensor1053 ptr = start;1054 while (ptr->next != end) {1055 ptr = ptr->next;1056 Vector x;1057 x.CopyVector(&ptr->x);1058 //x.SubtractVector(CenterOfGravity);1059 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);1060 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);1061 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);1062 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);1063 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);1064 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);1065 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);1066 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);1067 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);1068 }1069 // print InertiaTensor for debugging1070 *out << "The inertia tensor is:" << endl;1071 for(int i=0;i<NDIM;i++) {1072 for(int j=0;j<NDIM;j++)1073 *out << InertiaTensor[i*NDIM+j] << " ";1074 *out << endl;1075 }1076 *out << endl;1077 }1078 1079 // free everything1080 delete(CenterOfGravity);1081 gsl_vector_free(eval);1082 gsl_matrix_free(evec);985 atom *ptr = start; // start at first in list 986 double InertiaTensor[NDIM*NDIM]; 987 Vector *CenterOfGravity = DetermineCenterOfGravity(out); 988 989 CenterGravity(out, CenterOfGravity); 990 991 // reset inertia tensor 992 for(int i=0;i<NDIM*NDIM;i++) 993 InertiaTensor[i] = 0.; 994 995 // sum up inertia tensor 996 while (ptr->next != end) { 997 ptr = ptr->next; 998 Vector x; 999 x.CopyVector(&ptr->x); 1000 //x.SubtractVector(CenterOfGravity); 1001 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1002 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1003 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1004 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1005 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1006 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1007 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1008 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1009 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1010 } 1011 // print InertiaTensor for debugging 1012 *out << "The inertia tensor is:" << endl; 1013 for(int i=0;i<NDIM;i++) { 1014 for(int j=0;j<NDIM;j++) 1015 *out << InertiaTensor[i*NDIM+j] << " "; 1016 *out << endl; 1017 } 1018 *out << endl; 1019 1020 // diagonalize to determine principal axis system 1021 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); 1022 gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM); 1023 gsl_vector *eval = gsl_vector_alloc(NDIM); 1024 gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM); 1025 gsl_eigen_symmv(&m.matrix, eval, evec, T); 1026 gsl_eigen_symmv_free(T); 1027 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 1028 1029 for(int i=0;i<NDIM;i++) { 1030 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 1031 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 1032 } 1033 1034 // check whether we rotate or not 1035 if (DoRotate) { 1036 *out << Verbose(1) << "Transforming molecule into PAS ... "; 1037 // the eigenvectors specify the transformation matrix 1038 ptr = start; 1039 while (ptr->next != end) { 1040 ptr = ptr->next; 1041 for (int j=0;j<MDSteps;j++) 1042 Trajectories[ptr].R.at(j).MatrixMultiplication(evec->data); 1043 ptr->x.MatrixMultiplication(evec->data); 1044 } 1045 *out << "done." << endl; 1046 1047 // summing anew for debugging (resulting matrix has to be diagonal!) 1048 // reset inertia tensor 1049 for(int i=0;i<NDIM*NDIM;i++) 1050 InertiaTensor[i] = 0.; 1051 1052 // sum up inertia tensor 1053 ptr = start; 1054 while (ptr->next != end) { 1055 ptr = ptr->next; 1056 Vector x; 1057 x.CopyVector(&ptr->x); 1058 //x.SubtractVector(CenterOfGravity); 1059 InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]); 1060 InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]); 1061 InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]); 1062 InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]); 1063 InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]); 1064 InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]); 1065 InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]); 1066 InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]); 1067 InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]); 1068 } 1069 // print InertiaTensor for debugging 1070 *out << "The inertia tensor is:" << endl; 1071 for(int i=0;i<NDIM;i++) { 1072 for(int j=0;j<NDIM;j++) 1073 *out << InertiaTensor[i*NDIM+j] << " "; 1074 *out << endl; 1075 } 1076 *out << endl; 1077 } 1078 1079 // free everything 1080 delete(CenterOfGravity); 1081 gsl_vector_free(eval); 1082 gsl_matrix_free(evec); 1083 1083 }; 1084 1084 … … 1094 1094 bool molecule::VerletForceIntegration(char *file, double delta_t, bool IsAngstroem) 1095 1095 { 1096 element *runner = elemente->start;1097 atom *walker = NULL;1098 int AtomNo;1099 ifstream input(file);1100 string token;1101 stringstream item;1102 double a, IonMass;1103 ForceMatrix Force;1104 Vector tmpvector;1105 1106 CountElements();// make sure ElementsInMolecule is up to date1107 1108 // check file1109 if (input == NULL) {1110 return false;1111 } else {1112 // parse file into ForceMatrix1113 if (!Force.ParseMatrix(file, 0,0,0)) {1114 cerr << "Could not parse Force Matrix file " << file << "." << endl;1115 return false;1116 }1117 if (Force.RowCounter[0] != AtomCount) {1118 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl;1119 return false;1120 }1121 // correct Forces1122 // for(int d=0;d<NDIM;d++)1123 // tmpvector.x[d] = 0.;1124 // for(int i=0;i<AtomCount;i++)1125 // for(int d=0;d<NDIM;d++) {1126 // tmpvector.x[d] += Force.Matrix[0][i][d+5];1127 // }1128 // for(int i=0;i<AtomCount;i++)1129 // for(int d=0;d<NDIM;d++) {1130 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount;1131 // }1132 // and perform Verlet integration for each atom with position, velocity and force vector1133 runner = elemente->start;1134 while (runner->next != elemente->end) { // go through every element1135 runner = runner->next;1136 IonMass = runner->mass;1137 a = delta_t*0.5/IonMass;// (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a1138 if (ElementsInMolecule[runner->Z]) { // if this element got atoms1139 AtomNo = 0;1140 walker = start;1141 while (walker->next != end) { // go through every atom of this element1142 walker = walker->next;1143 if (walker->type == runner) { // if this atom fits to element1144 // check size of vectors1145 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) {1146 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl;1147 Trajectories[walker].R.resize(MDSteps+10);1148 Trajectories[walker].U.resize(MDSteps+10);1149 Trajectories[walker].F.resize(MDSteps+10);1150 }1151 // 1. calculate x(t+\delta t)1152 for (int d=0; d<NDIM; d++) {1153 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5];1154 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d];1155 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]);1156 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 * t1157 }1158 // 2. Calculate v(t+\delta t)1159 for (int d=0; d<NDIM; d++) {1160 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d];1161 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;1162 }1163 // cout << "Integrated position&velocity of step " << (MDSteps) << ": (";1164 // for (int d=0;d<NDIM;d++)1165 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " ";// next step1166 // cout << ")\t(";1167 // for (int d=0;d<NDIM;d++)1168 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " ";// next step1169 // cout << ")" << endl;1170 // next atom1171 AtomNo++;1172 }1173 }1174 }1175 }1176 }1177 // // correct velocities (rather momenta) so that center of mass remains motionless1178 // tmpvector.zero()1179 // IonMass = 0.;1180 // walker = start;1181 // while (walker->next != end) { // go through every atom1182 // walker = walker->next;1183 // IonMass += walker->type->mass;// sum up total mass1184 // for(int d=0;d<NDIM;d++) {1185 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass;1186 // }1187 // }1188 // walker = start;1189 // while (walker->next != end) { // go through every atom of this element1190 // walker = walker->next;1191 // for(int d=0;d<NDIM;d++) {1192 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass;1193 // }1194 // }1195 MDSteps++;1196 1197 1198 // exit1199 return true;1096 element *runner = elemente->start; 1097 atom *walker = NULL; 1098 int AtomNo; 1099 ifstream input(file); 1100 string token; 1101 stringstream item; 1102 double a, IonMass; 1103 ForceMatrix Force; 1104 Vector tmpvector; 1105 1106 CountElements(); // make sure ElementsInMolecule is up to date 1107 1108 // check file 1109 if (input == NULL) { 1110 return false; 1111 } else { 1112 // parse file into ForceMatrix 1113 if (!Force.ParseMatrix(file, 0,0,0)) { 1114 cerr << "Could not parse Force Matrix file " << file << "." << endl; 1115 return false; 1116 } 1117 if (Force.RowCounter[0] != AtomCount) { 1118 cerr << "Mismatch between number of atoms in file " << Force.RowCounter[0] << " and in molecule " << AtomCount << "." << endl; 1119 return false; 1120 } 1121 // correct Forces 1122 // for(int d=0;d<NDIM;d++) 1123 // tmpvector.x[d] = 0.; 1124 // for(int i=0;i<AtomCount;i++) 1125 // for(int d=0;d<NDIM;d++) { 1126 // tmpvector.x[d] += Force.Matrix[0][i][d+5]; 1127 // } 1128 // for(int i=0;i<AtomCount;i++) 1129 // for(int d=0;d<NDIM;d++) { 1130 // Force.Matrix[0][i][d+5] -= tmpvector.x[d]/(double)AtomCount; 1131 // } 1132 // and perform Verlet integration for each atom with position, velocity and force vector 1133 runner = elemente->start; 1134 while (runner->next != elemente->end) { // go through every element 1135 runner = runner->next; 1136 IonMass = runner->mass; 1137 a = delta_t*0.5/IonMass; // (F+F_old)/2m = a and thus: v = (F+F_old)/2m * t = (F + F_old) * a 1138 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 1139 AtomNo = 0; 1140 walker = start; 1141 while (walker->next != end) { // go through every atom of this element 1142 walker = walker->next; 1143 if (walker->type == runner) { // if this atom fits to element 1144 // check size of vectors 1145 if (Trajectories[walker].R.size() <= (unsigned int)(MDSteps)) { 1146 //cout << "Increasing size for trajectory array of " << *walker << " to " << (size+10) << "." << endl; 1147 Trajectories[walker].R.resize(MDSteps+10); 1148 Trajectories[walker].U.resize(MDSteps+10); 1149 Trajectories[walker].F.resize(MDSteps+10); 1150 } 1151 // 1. calculate x(t+\delta t) 1152 for (int d=0; d<NDIM; d++) { 1153 Trajectories[walker].F.at(MDSteps).x[d] = -Force.Matrix[0][AtomNo][d+5]; 1154 Trajectories[walker].R.at(MDSteps).x[d] = Trajectories[walker].R.at(MDSteps-1).x[d]; 1155 Trajectories[walker].R.at(MDSteps).x[d] += delta_t*(Trajectories[walker].U.at(MDSteps-1).x[d]); 1156 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 1157 } 1158 // 2. Calculate v(t+\delta t) 1159 for (int d=0; d<NDIM; d++) { 1160 Trajectories[walker].U.at(MDSteps).x[d] = Trajectories[walker].U.at(MDSteps-1).x[d]; 1161 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; 1162 } 1163 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1164 // for (int d=0;d<NDIM;d++) 1165 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step 1166 // cout << ")\t("; 1167 // for (int d=0;d<NDIM;d++) 1168 // cout << Trajectories[walker].U.at(MDSteps).x[d] << " "; // next step 1169 // cout << ")" << endl; 1170 // next atom 1171 AtomNo++; 1172 } 1173 } 1174 } 1175 } 1176 } 1177 // // correct velocities (rather momenta) so that center of mass remains motionless 1178 // tmpvector.zero() 1179 // IonMass = 0.; 1180 // walker = start; 1181 // while (walker->next != end) { // go through every atom 1182 // walker = walker->next; 1183 // IonMass += walker->type->mass; // sum up total mass 1184 // for(int d=0;d<NDIM;d++) { 1185 // tmpvector.x[d] += Trajectories[walker].U.at(MDSteps).x[d]*walker->type->mass; 1186 // } 1187 // } 1188 // walker = start; 1189 // while (walker->next != end) { // go through every atom of this element 1190 // walker = walker->next; 1191 // for(int d=0;d<NDIM;d++) { 1192 // Trajectories[walker].U.at(MDSteps).x[d] -= tmpvector.x[d]*walker->type->mass/IonMass; 1193 // } 1194 // } 1195 MDSteps++; 1196 1197 1198 // exit 1199 return true; 1200 1200 }; 1201 1201 … … 1205 1205 void molecule::Align(Vector *n) 1206 1206 { 1207 atom *ptr = start;1208 double alpha, tmp;1209 Vector z_axis;1210 z_axis.x[0] = 0.;1211 z_axis.x[1] = 0.;1212 z_axis.x[2] = 1.;1213 1214 // rotate on z-x plane1215 cout << Verbose(0) << "Begin of Aligning all atoms." << endl;1216 alpha = atan(-n->x[0]/n->x[2]);1217 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... ";1218 while (ptr->next != end) {1219 ptr = ptr->next;1220 tmp = ptr->x.x[0];1221 ptr->x.x[0] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1222 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1223 for (int j=0;j<MDSteps;j++) {1224 tmp = Trajectories[ptr].R.at(j).x[0];1225 Trajectories[ptr].R.at(j).x[0] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1226 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1227 }1228 }1229 // rotate n vector1230 tmp = n->x[0];1231 n->x[0] = cos(alpha) * tmp +sin(alpha) * n->x[2];1232 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1233 cout << Verbose(1) << "alignment vector after first rotation: ";1234 n->Output((ofstream *)&cout);1235 cout << endl;1236 1237 // rotate on z-y plane1238 ptr = start;1239 alpha = atan(-n->x[1]/n->x[2]);1240 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... ";1241 while (ptr->next != end) {1242 ptr = ptr->next;1243 tmp = ptr->x.x[1];1244 ptr->x.x[1] =cos(alpha) * tmp + sin(alpha) * ptr->x.x[2];1245 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2];1246 for (int j=0;j<MDSteps;j++) {1247 tmp = Trajectories[ptr].R.at(j).x[1];1248 Trajectories[ptr].R.at(j).x[1] =cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2];1249 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2];1250 }1251 }1252 // rotate n vector (for consistency check)1253 tmp = n->x[1];1254 n->x[1] = cos(alpha) * tmp +sin(alpha) * n->x[2];1255 n->x[2] = -sin(alpha) * tmp +cos(alpha) * n->x[2];1256 1257 cout << Verbose(1) << "alignment vector after second rotation: ";1258 n->Output((ofstream *)&cout);1259 cout << Verbose(1) << endl;1260 cout << Verbose(0) << "End of Aligning all atoms." << endl;1207 atom *ptr = start; 1208 double alpha, tmp; 1209 Vector z_axis; 1210 z_axis.x[0] = 0.; 1211 z_axis.x[1] = 0.; 1212 z_axis.x[2] = 1.; 1213 1214 // rotate on z-x plane 1215 cout << Verbose(0) << "Begin of Aligning all atoms." << endl; 1216 alpha = atan(-n->x[0]/n->x[2]); 1217 cout << Verbose(1) << "Z-X-angle: " << alpha << " ... "; 1218 while (ptr->next != end) { 1219 ptr = ptr->next; 1220 tmp = ptr->x.x[0]; 1221 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1222 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1223 for (int j=0;j<MDSteps;j++) { 1224 tmp = Trajectories[ptr].R.at(j).x[0]; 1225 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1226 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1227 } 1228 } 1229 // rotate n vector 1230 tmp = n->x[0]; 1231 n->x[0] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1232 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1233 cout << Verbose(1) << "alignment vector after first rotation: "; 1234 n->Output((ofstream *)&cout); 1235 cout << endl; 1236 1237 // rotate on z-y plane 1238 ptr = start; 1239 alpha = atan(-n->x[1]/n->x[2]); 1240 cout << Verbose(1) << "Z-Y-angle: " << alpha << " ... "; 1241 while (ptr->next != end) { 1242 ptr = ptr->next; 1243 tmp = ptr->x.x[1]; 1244 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1245 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1246 for (int j=0;j<MDSteps;j++) { 1247 tmp = Trajectories[ptr].R.at(j).x[1]; 1248 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1249 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1250 } 1251 } 1252 // rotate n vector (for consistency check) 1253 tmp = n->x[1]; 1254 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1255 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1256 1257 cout << Verbose(1) << "alignment vector after second rotation: "; 1258 n->Output((ofstream *)&cout); 1259 cout << Verbose(1) << endl; 1260 cout << Verbose(0) << "End of Aligning all atoms." << endl; 1261 1261 }; 1262 1262 … … 1267 1267 bool molecule::RemoveAtom(atom *pointer) 1268 1268 { 1269 if (ElementsInMolecule[pointer->type->Z] != 0)// this would indicate an error1270 ElementsInMolecule[pointer->type->Z]--;// decrease number of atom of this element1271 else1272 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl;1273 if (ElementsInMolecule[pointer->type->Z] == 0)// was last atom of this element?1274 ElementCount--;1275 Trajectories.erase(pointer);1276 return remove(pointer, start, end);1269 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1270 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1271 else 1272 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1273 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1274 ElementCount--; 1275 Trajectories.erase(pointer); 1276 return remove(pointer, start, end); 1277 1277 }; 1278 1278 … … 1301 1301 bool molecule::CleanupMolecule() 1302 1302 { 1303 return (cleanup(start,end) && cleanup(first,last));1303 return (cleanup(start,end) && cleanup(first,last)); 1304 1304 }; 1305 1305 … … 1308 1308 * \return pointer to atom or NULL 1309 1309 */ 1310 atom * molecule::FindAtom(int Nr) const{1311 atom * walker = find(&Nr, start,end);1312 if (walker != NULL) {1313 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl;1314 return walker;1315 } else {1316 cout << Verbose(0) << "Atom not found in list." << endl;1317 return NULL;1318 }1310 atom * molecule::FindAtom(int Nr) const{ 1311 atom * walker = find(&Nr, start,end); 1312 if (walker != NULL) { 1313 //cout << Verbose(0) << "Found Atom Nr. " << walker->nr << endl; 1314 return walker; 1315 } else { 1316 cout << Verbose(0) << "Atom not found in list." << endl; 1317 return NULL; 1318 } 1319 1319 }; 1320 1320 … … 1324 1324 atom * molecule::AskAtom(string text) 1325 1325 { 1326 int No;1327 atom *ion = NULL;1328 do {1329 //cout << Verbose(0) << "============Atom list==========================" << endl;1330 //mol->Output((ofstream *)&cout);1331 //cout << Verbose(0) << "===============================================" << endl;1332 cout << Verbose(0) << text;1333 cin >> No;1334 ion = this->FindAtom(No);1335 } while (ion == NULL);1336 return ion;1326 int No; 1327 atom *ion = NULL; 1328 do { 1329 //cout << Verbose(0) << "============Atom list==========================" << endl; 1330 //mol->Output((ofstream *)&cout); 1331 //cout << Verbose(0) << "===============================================" << endl; 1332 cout << Verbose(0) << text; 1333 cin >> No; 1334 ion = this->FindAtom(No); 1335 } while (ion == NULL); 1336 return ion; 1337 1337 }; 1338 1338 … … 1343 1343 bool molecule::CheckBounds(const Vector *x) const 1344 1344 { 1345 bool result = true;1346 int j =-1;1347 for (int i=0;i<NDIM;i++) {1348 j += i+1;1349 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j]));1350 }1351 //return result;1352 return true; /// probably not gonna use the check no more1345 bool result = true; 1346 int j =-1; 1347 for (int i=0;i<NDIM;i++) { 1348 j += i+1; 1349 result = result && ((x->x[i] >= 0) && (x->x[i] < cell_size[j])); 1350 } 1351 //return result; 1352 return true; /// probably not gonna use the check no more 1353 1353 }; 1354 1354 … … 1360 1360 double LeastSquareDistance (const gsl_vector * x, void * params) 1361 1361 { 1362 double res = 0, t;1363 Vector a,b,c,d;1364 struct lsq_params *par = (struct lsq_params *)params;1365 atom *ptr = par->mol->start;1366 1367 // initialize vectors1368 a.x[0] = gsl_vector_get(x,0);1369 a.x[1] = gsl_vector_get(x,1);1370 a.x[2] = gsl_vector_get(x,2);1371 b.x[0] = gsl_vector_get(x,3);1372 b.x[1] = gsl_vector_get(x,4);1373 b.x[2] = gsl_vector_get(x,5);1374 // go through all atoms1375 while (ptr != par->mol->end) {1376 ptr = ptr->next;1377 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type1378 c.CopyVector(&ptr->x);// copy vector to temporary one1379 c.SubtractVector(&a);// subtract offset vector1380 t = c.ScalarProduct(&b);// get direction parameter1381 d.CopyVector(&b);// and create vector1382 d.Scale(&t);1383 c.SubtractVector(&d);// ... yielding distance vector1384 res += d.ScalarProduct((const Vector *)&d);// add squared distance1385 }1386 }1387 return res;1362 double res = 0, t; 1363 Vector a,b,c,d; 1364 struct lsq_params *par = (struct lsq_params *)params; 1365 atom *ptr = par->mol->start; 1366 1367 // initialize vectors 1368 a.x[0] = gsl_vector_get(x,0); 1369 a.x[1] = gsl_vector_get(x,1); 1370 a.x[2] = gsl_vector_get(x,2); 1371 b.x[0] = gsl_vector_get(x,3); 1372 b.x[1] = gsl_vector_get(x,4); 1373 b.x[2] = gsl_vector_get(x,5); 1374 // go through all atoms 1375 while (ptr != par->mol->end) { 1376 ptr = ptr->next; 1377 if (ptr->type == ((struct lsq_params *)params)->type) { // for specific type 1378 c.CopyVector(&ptr->x); // copy vector to temporary one 1379 c.SubtractVector(&a); // subtract offset vector 1380 t = c.ScalarProduct(&b); // get direction parameter 1381 d.CopyVector(&b); // and create vector 1382 d.Scale(&t); 1383 c.SubtractVector(&d); // ... yielding distance vector 1384 res += d.ScalarProduct((const Vector *)&d); // add squared distance 1385 } 1386 } 1387 return res; 1388 1388 }; 1389 1389 … … 1393 1393 void molecule::GetAlignvector(struct lsq_params * par) const 1394 1394 { 1395 int np = 6;1396 1397 const gsl_multimin_fminimizer_type *T =1398 gsl_multimin_fminimizer_nmsimplex;1399 gsl_multimin_fminimizer *s = NULL;1400 gsl_vector *ss;1401 gsl_multimin_function minex_func;1402 1403 size_t iter = 0, i;1404 int status;1405 double size;1406 1407 /* Initial vertex size vector */1408 ss = gsl_vector_alloc (np);1409 1410 /* Set all step sizes to 1 */1411 gsl_vector_set_all (ss, 1.0);1412 1413 /* Starting point */1414 par->x = gsl_vector_alloc (np);1415 par->mol = this;1416 1417 gsl_vector_set (par->x, 0, 0.0);// offset1418 gsl_vector_set (par->x, 1, 0.0);1419 gsl_vector_set (par->x, 2, 0.0);1420 gsl_vector_set (par->x, 3, 0.0);// direction1421 gsl_vector_set (par->x, 4, 0.0);1422 gsl_vector_set (par->x, 5, 1.0);1423 1424 /* Initialize method and iterate */1425 minex_func.f = &LeastSquareDistance;1426 minex_func.n = np;1427 minex_func.params = (void *)par;1428 1429 s = gsl_multimin_fminimizer_alloc (T, np);1430 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss);1431 1432 do1433 {1434 iter++;1435 status = gsl_multimin_fminimizer_iterate(s);1436 1437 if (status)1438 break;1439 1440 size = gsl_multimin_fminimizer_size (s);1441 status = gsl_multimin_test_size (size, 1e-2);1442 1443 if (status == GSL_SUCCESS)1444 {1445 printf ("converged to minimum at\n");1446 }1447 1448 printf ("%5d ", (int)iter);1449 for (i = 0; i < (size_t)np; i++)1450 {1451 printf ("%10.3e ", gsl_vector_get (s->x, i));1452 }1453 printf ("f() = %7.3f size = %.3f\n", s->fval, size);1454 }1455 while (status == GSL_CONTINUE && iter < 100);1456 1457 for (i=0;i<(size_t)np;i++)1458 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i));1459 //gsl_vector_free(par->x);1460 gsl_vector_free(ss);1461 gsl_multimin_fminimizer_free (s);1395 int np = 6; 1396 1397 const gsl_multimin_fminimizer_type *T = 1398 gsl_multimin_fminimizer_nmsimplex; 1399 gsl_multimin_fminimizer *s = NULL; 1400 gsl_vector *ss; 1401 gsl_multimin_function minex_func; 1402 1403 size_t iter = 0, i; 1404 int status; 1405 double size; 1406 1407 /* Initial vertex size vector */ 1408 ss = gsl_vector_alloc (np); 1409 1410 /* Set all step sizes to 1 */ 1411 gsl_vector_set_all (ss, 1.0); 1412 1413 /* Starting point */ 1414 par->x = gsl_vector_alloc (np); 1415 par->mol = this; 1416 1417 gsl_vector_set (par->x, 0, 0.0); // offset 1418 gsl_vector_set (par->x, 1, 0.0); 1419 gsl_vector_set (par->x, 2, 0.0); 1420 gsl_vector_set (par->x, 3, 0.0); // direction 1421 gsl_vector_set (par->x, 4, 0.0); 1422 gsl_vector_set (par->x, 5, 1.0); 1423 1424 /* Initialize method and iterate */ 1425 minex_func.f = &LeastSquareDistance; 1426 minex_func.n = np; 1427 minex_func.params = (void *)par; 1428 1429 s = gsl_multimin_fminimizer_alloc (T, np); 1430 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1431 1432 do 1433 { 1434 iter++; 1435 status = gsl_multimin_fminimizer_iterate(s); 1436 1437 if (status) 1438 break; 1439 1440 size = gsl_multimin_fminimizer_size (s); 1441 status = gsl_multimin_test_size (size, 1e-2); 1442 1443 if (status == GSL_SUCCESS) 1444 { 1445 printf ("converged to minimum at\n"); 1446 } 1447 1448 printf ("%5d ", (int)iter); 1449 for (i = 0; i < (size_t)np; i++) 1450 { 1451 printf ("%10.3e ", gsl_vector_get (s->x, i)); 1452 } 1453 printf ("f() = %7.3f size = %.3f\n", s->fval, size); 1454 } 1455 while (status == GSL_CONTINUE && iter < 100); 1456 1457 for (i=0;i<(size_t)np;i++) 1458 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); 1459 //gsl_vector_free(par->x); 1460 gsl_vector_free(ss); 1461 gsl_multimin_fminimizer_free (s); 1462 1462 }; 1463 1463 … … 1467 1467 bool molecule::Output(ofstream *out) 1468 1468 { 1469 atom *walker = NULL;1470 int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS];1471 CountElements();1472 1473 for (int i=0;i<MAX_ELEMENTS;++i) {1474 AtomNo[i] = 0;1475 ElementNo[i] = 0;1476 }1477 if (out == NULL) {1478 return false;1479 } else {1480 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1469 atom *walker = NULL; 1470 int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS]; 1471 CountElements(); 1472 1473 for (int i=0;i<MAX_ELEMENTS;++i) { 1474 AtomNo[i] = 0; 1475 ElementNo[i] = 0; 1476 } 1477 if (out == NULL) { 1478 return false; 1479 } else { 1480 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1481 1481 walker = start; 1482 1482 while (walker->next != end) { // go through every atom of this element … … 1495 1495 walker->Output(ElementNo[walker->type->Z], AtomNo[walker->type->Z], out); // removed due to trajectories 1496 1496 } 1497 return true;1498 }1497 return true; 1498 } 1499 1499 }; 1500 1500 … … 1504 1504 bool molecule::OutputTrajectories(ofstream *out) 1505 1505 { 1506 atom *walker = NULL;1506 atom *walker = NULL; 1507 1507 int ElementNo[MAX_ELEMENTS], AtomNo[MAX_ELEMENTS]; 1508 CountElements();1509 1510 if (out == NULL) {1511 return false;1512 } else {1513 for (int step = 0; step < MDSteps; step++) {1514 if (step == 0) {1515 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2]MoveType (0 MoveIon, 1 FixedIon)" << endl;1516 } else {1517 *out << "# ====== MD step " << step << " =========" << endl;1518 }1519 for (int i=0;i<MAX_ELEMENTS;++i) {1520 AtomNo[i] = 0;1521 ElementNo[i] = 0;1522 }1508 CountElements(); 1509 1510 if (out == NULL) { 1511 return false; 1512 } else { 1513 for (int step = 0; step < MDSteps; step++) { 1514 if (step == 0) { 1515 *out << "#Ion_TypeNr._Nr.R[0] R[1] R[2] MoveType (0 MoveIon, 1 FixedIon)" << endl; 1516 } else { 1517 *out << "# ====== MD step " << step << " =========" << endl; 1518 } 1519 for (int i=0;i<MAX_ELEMENTS;++i) { 1520 AtomNo[i] = 0; 1521 ElementNo[i] = 0; 1522 } 1523 1523 walker = start; 1524 1524 while (walker->next != end) { // go through every atom of this element … … 1535 1535 walker = walker->next; 1536 1536 AtomNo[walker->type->Z]++; 1537 *out << "Ion_Type" << ElementNo[walker->type->Z] << "_" << AtomNo[walker->type->Z] << "\t" << fixed << setprecision(9) << showpoint;1537 *out << "Ion_Type" << ElementNo[walker->type->Z] << "_" << AtomNo[walker->type->Z] << "\t" << fixed << setprecision(9) << showpoint; 1538 1538 *out << Trajectories[walker].R.at(step).x[0] << "\t" << Trajectories[walker].R.at(step).x[1] << "\t" << Trajectories[walker].R.at(step).x[2]; 1539 1539 *out << "\t" << walker->FixedIon; … … 1544 1544 *out << "\t# Number in molecule " << walker->nr << endl; 1545 1545 } 1546 }1547 return true;1548 }1546 } 1547 return true; 1548 } 1549 1549 }; 1550 1550 … … 1554 1554 void molecule::OutputListOfBonds(ofstream *out) const 1555 1555 { 1556 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl;1557 atom *Walker = start;1558 while (Walker->next != end) {1559 Walker = Walker->next;1556 *out << Verbose(2) << endl << "From Contents of ListOfBondsPerAtom, all non-hydrogen atoms:" << endl; 1557 atom *Walker = start; 1558 while (Walker->next != end) { 1559 Walker = Walker->next; 1560 1560 #ifdef ADDHYDROGEN 1561 if (Walker->type->Z != 1) {// regard only non-hydrogen1561 if (Walker->type->Z != 1) { // regard only non-hydrogen 1562 1562 #endif 1563 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl;1564 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {1565 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl;1566 }1563 *out << Verbose(2) << "Atom " << Walker->Name << " has Bonds: "<<endl; 1564 for(int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 1565 *out << Verbose(3) << *(ListOfBondsPerAtom)[Walker->nr][j] << endl; 1566 } 1567 1567 #ifdef ADDHYDROGEN 1568 }1568 } 1569 1569 #endif 1570 }1571 *out << endl;1570 } 1571 *out << endl; 1572 1572 }; 1573 1573 … … 1575 1575 * \param *out stream pointer 1576 1576 */ 1577 bool molecule::Checkout(ofstream *out) const1578 { 1579 return elemente->Checkout(out, ElementsInMolecule);1577 bool molecule::Checkout(ofstream *out) const 1578 { 1579 return elemente->Checkout(out, ElementsInMolecule); 1580 1580 }; 1581 1581 … … 1585 1585 bool molecule::OutputTrajectoriesXYZ(ofstream *out) 1586 1586 { 1587 atom *walker = NULL;1588 int No = 0;1589 time_t now;1590 1591 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1592 walker = start;1593 while (walker->next != end) { // go through every atom and count1594 walker = walker->next;1595 No++;1596 }1597 if (out != NULL) {1598 for (int step=0;step<MDSteps;step++) {1599 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now);1600 walker = start;1601 while (walker->next != end) { // go through every atom of this element1602 walker = walker->next;1603 *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;1604 }1605 }1606 return true;1607 } else1608 return false;1587 atom *walker = NULL; 1588 int No = 0; 1589 time_t now; 1590 1591 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1592 walker = start; 1593 while (walker->next != end) { // go through every atom and count 1594 walker = walker->next; 1595 No++; 1596 } 1597 if (out != NULL) { 1598 for (int step=0;step<MDSteps;step++) { 1599 *out << No << "\n\tCreated by molecuilder, step " << step << ", on " << ctime(&now); 1600 walker = start; 1601 while (walker->next != end) { // go through every atom of this element 1602 walker = walker->next; 1603 *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; 1604 } 1605 } 1606 return true; 1607 } else 1608 return false; 1609 1609 }; 1610 1610 … … 1614 1614 bool molecule::OutputXYZ(ofstream *out) const 1615 1615 { 1616 atom *walker = NULL;1617 int AtomNo = 0;1618 time_t now;1619 1620 now = time((time_t *)NULL);// Get the system time and put it into 'now' as 'calender time'1621 walker = start;1622 while (walker->next != end) { // go through every atom and count1623 walker = walker->next;1624 AtomNo++;1625 }1626 if (out != NULL) {1627 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now);1616 atom *walker = NULL; 1617 int AtomNo = 0; 1618 time_t now; 1619 1620 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1621 walker = start; 1622 while (walker->next != end) { // go through every atom and count 1623 walker = walker->next; 1624 AtomNo++; 1625 } 1626 if (out != NULL) { 1627 *out << AtomNo << "\n\tCreated by molecuilder on " << ctime(&now); 1628 1628 walker = start; 1629 1629 while (walker->next != end) { // go through every atom of this element … … 1631 1631 walker->OutputXYZLine(out); 1632 1632 } 1633 return true;1634 } else1635 return false;1633 return true; 1634 } else 1635 return false; 1636 1636 }; 1637 1637 … … 1641 1641 void molecule::CountAtoms(ofstream *out) 1642 1642 { 1643 int i = 0;1644 atom *Walker = start;1645 while (Walker->next != end) {1646 Walker = Walker->next;1647 i++;1648 }1649 if ((AtomCount == 0) || (i != AtomCount)) {1650 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl;1651 AtomCount = i;1652 1653 // count NonHydrogen atoms and give each atom a unique name1654 if (AtomCount != 0) {1655 i=0;1656 NoNonHydrogen = 0;1657 Walker = start;1658 while (Walker->next != end) {1659 Walker = Walker->next;1660 Walker->nr = i;// update number in molecule (for easier referencing in FragmentMolecule lateron)1661 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it1662 NoNonHydrogen++;1663 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name");1664 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name");1665 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1);1666 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl;1667 i++;1668 }1669 } else1670 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl;1671 }1643 int i = 0; 1644 atom *Walker = start; 1645 while (Walker->next != end) { 1646 Walker = Walker->next; 1647 i++; 1648 } 1649 if ((AtomCount == 0) || (i != AtomCount)) { 1650 *out << Verbose(3) << "Mismatch in AtomCount " << AtomCount << " and recounted number " << i << ", renaming all." << endl; 1651 AtomCount = i; 1652 1653 // count NonHydrogen atoms and give each atom a unique name 1654 if (AtomCount != 0) { 1655 i=0; 1656 NoNonHydrogen = 0; 1657 Walker = start; 1658 while (Walker->next != end) { 1659 Walker = Walker->next; 1660 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1661 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1662 NoNonHydrogen++; 1663 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1664 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); 1665 sprintf(Walker->Name, "%2s%02d", Walker->type->symbol, Walker->nr+1); 1666 *out << "Naming atom nr. " << Walker->nr << " " << Walker->Name << "." << endl; 1667 i++; 1668 } 1669 } else 1670 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1671 } 1672 1672 }; 1673 1673 … … 1676 1676 void molecule::CountElements() 1677 1677 { 1678 int i = 0;1679 for(i=MAX_ELEMENTS;i--;)1680 ElementsInMolecule[i] = 0;1681 ElementCount = 0;1682 1683 atom *walker = start;1684 while (walker->next != end) {1685 walker = walker->next;1686 ElementsInMolecule[walker->type->Z]++;1687 i++;1688 }1689 for(i=MAX_ELEMENTS;i--;)1690 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0);1678 int i = 0; 1679 for(i=MAX_ELEMENTS;i--;) 1680 ElementsInMolecule[i] = 0; 1681 ElementCount = 0; 1682 1683 atom *walker = start; 1684 while (walker->next != end) { 1685 walker = walker->next; 1686 ElementsInMolecule[walker->type->Z]++; 1687 i++; 1688 } 1689 for(i=MAX_ELEMENTS;i--;) 1690 ElementCount += (ElementsInMolecule[i] != 0 ? 1 : 0); 1691 1691 }; 1692 1692 … … 1698 1698 int molecule::CountCyclicBonds(ofstream *out) 1699 1699 { 1700 int No = 0;1701 int *MinimumRingSize = NULL;1702 MoleculeLeafClass *Subgraphs = NULL;1703 class StackClass<bond *> *BackEdgeStack = NULL;1704 bond *Binder = first;1705 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {1706 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;1707 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);1708 while (Subgraphs->next != NULL) {1709 Subgraphs = Subgraphs->next;1710 delete(Subgraphs->previous);1711 }1712 delete(Subgraphs);1713 delete[](MinimumRingSize);1714 }1715 while(Binder->next != last) {1716 Binder = Binder->next;1717 if (Binder->Cyclic)1718 No++;1719 }1720 delete(BackEdgeStack);1721 return No;1700 int No = 0; 1701 int *MinimumRingSize = NULL; 1702 MoleculeLeafClass *Subgraphs = NULL; 1703 class StackClass<bond *> *BackEdgeStack = NULL; 1704 bond *Binder = first; 1705 if ((Binder->next != last) && (Binder->next->Type == Undetermined)) { 1706 *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl; 1707 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 1708 while (Subgraphs->next != NULL) { 1709 Subgraphs = Subgraphs->next; 1710 delete(Subgraphs->previous); 1711 } 1712 delete(Subgraphs); 1713 delete[](MinimumRingSize); 1714 } 1715 while(Binder->next != last) { 1716 Binder = Binder->next; 1717 if (Binder->Cyclic) 1718 No++; 1719 } 1720 delete(BackEdgeStack); 1721 return No; 1722 1722 }; 1723 1723 /** Returns Shading as a char string. … … 1727 1727 string molecule::GetColor(enum Shading color) 1728 1728 { 1729 switch(color) {1730 case white:1731 return "white";1732 break;1733 case lightgray:1734 return "lightgray";1735 break;1736 case darkgray:1737 return "darkgray";1738 break;1739 case black:1740 return "black";1741 break;1742 default:1743 return "uncolored";1744 break;1745 };1729 switch(color) { 1730 case white: 1731 return "white"; 1732 break; 1733 case lightgray: 1734 return "lightgray"; 1735 break; 1736 case darkgray: 1737 return "darkgray"; 1738 break; 1739 case black: 1740 return "black"; 1741 break; 1742 default: 1743 return "uncolored"; 1744 break; 1745 }; 1746 1746 }; 1747 1747 … … 1752 1752 void molecule::CalculateOrbitals(class config &configuration) 1753 1753 { 1754 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0;1755 for(int i=MAX_ELEMENTS;i--;) {1756 if (ElementsInMolecule[i] != 0) {1757 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl;1758 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence);1759 }1760 }1761 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2);1762 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2;1763 configuration.MaxPsiDouble /= 2;1764 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1;1765 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) {1766 configuration.ProcPEGamma /= 2;1767 configuration.ProcPEPsi *= 2;1768 } else {1769 configuration.ProcPEGamma *= configuration.ProcPEPsi;1770 configuration.ProcPEPsi = 1;1771 }1772 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble;1754 configuration.MaxPsiDouble = configuration.PsiMaxNoDown = configuration.PsiMaxNoUp = configuration.PsiType = 0; 1755 for(int i=MAX_ELEMENTS;i--;) { 1756 if (ElementsInMolecule[i] != 0) { 1757 //cout << "CalculateOrbitals: " << elemente->FindElement(i)->name << " has a valence of " << (int)elemente->FindElement(i)->Valence << " and there are " << ElementsInMolecule[i] << " of it." << endl; 1758 configuration.MaxPsiDouble += ElementsInMolecule[i]*((int)elemente->FindElement(i)->Valence); 1759 } 1760 } 1761 configuration.PsiMaxNoDown = configuration.MaxPsiDouble/2 + (configuration.MaxPsiDouble % 2); 1762 configuration.PsiMaxNoUp = configuration.MaxPsiDouble/2; 1763 configuration.MaxPsiDouble /= 2; 1764 configuration.PsiType = (configuration.PsiMaxNoDown == configuration.PsiMaxNoUp) ? 0 : 1; 1765 if ((configuration.PsiType == 1) && (configuration.ProcPEPsi < 2)) { 1766 configuration.ProcPEGamma /= 2; 1767 configuration.ProcPEPsi *= 2; 1768 } else { 1769 configuration.ProcPEGamma *= configuration.ProcPEPsi; 1770 configuration.ProcPEPsi = 1; 1771 } 1772 configuration.InitMaxMinStopStep = configuration.MaxMinStopStep = configuration.MaxPsiDouble; 1773 1773 }; 1774 1774 … … 1779 1779 { 1780 1780 1781 // 1 We will parse bonds out of the dbond file created by tremolo.1782 int atom1, atom2, temp;1783 atom *Walker, *OtherWalker;1784 1785 if (!input)1786 {1787 cout << Verbose(1) << "Opening silica failed \n";1788 };1789 1790 *input >> ws >> atom1;1791 *input >> ws >> atom2;1792 cout << Verbose(1) << "Scanning file\n";1793 while (!input->eof()) // Check whether we read everything already1794 {1795 *input >> ws >> atom1;1796 *input >> ws >> atom2;1797 if(atom2<atom1) //Sort indices of atoms in order1798 {1799 temp=atom1;1800 atom1=atom2;1801 atom2=temp;1802 };1803 1804 Walker=start;1805 while(Walker-> nr != atom1) // Find atom corresponding to first index1806 {1807 Walker = Walker->next;1808 };1809 OtherWalker = Walker->next;1810 while(OtherWalker->nr != atom2) // Find atom corresponding to second index1811 {1812 OtherWalker= OtherWalker->next;1813 };1814 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices.1815 1816 }1817 1818 CreateListOfBondsPerAtom(out);1781 // 1 We will parse bonds out of the dbond file created by tremolo. 1782 int atom1, atom2, temp; 1783 atom *Walker, *OtherWalker; 1784 1785 if (!input) 1786 { 1787 cout << Verbose(1) << "Opening silica failed \n"; 1788 }; 1789 1790 *input >> ws >> atom1; 1791 *input >> ws >> atom2; 1792 cout << Verbose(1) << "Scanning file\n"; 1793 while (!input->eof()) // Check whether we read everything already 1794 { 1795 *input >> ws >> atom1; 1796 *input >> ws >> atom2; 1797 if(atom2<atom1) //Sort indices of atoms in order 1798 { 1799 temp=atom1; 1800 atom1=atom2; 1801 atom2=temp; 1802 }; 1803 1804 Walker=start; 1805 while(Walker-> nr != atom1) // Find atom corresponding to first index 1806 { 1807 Walker = Walker->next; 1808 }; 1809 OtherWalker = Walker->next; 1810 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1811 { 1812 OtherWalker= OtherWalker->next; 1813 }; 1814 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1815 1816 } 1817 1818 CreateListOfBondsPerAtom(out); 1819 1819 1820 1820 }; … … 1827 1827 * To make it O(N log N) the function uses the linked-cell technique as follows: 1828 1828 * The procedure is step-wise: 1829 * -# Remove every bond in list1830 * -# Count the atoms in the molecule with CountAtoms()1831 * -# partition cell into smaller linked cells of size \a bonddistance1832 * -# put each atom into its corresponding cell1833 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true1834 * -# create the list of bonds via CreateListOfBondsPerAtom()1835 * -# correct the bond degree iteratively (single->double->triple bond)1836 * -# finally print the bond list to \a *out if desired1829 * -# Remove every bond in list 1830 * -# Count the atoms in the molecule with CountAtoms() 1831 * -# partition cell into smaller linked cells of size \a bonddistance 1832 * -# put each atom into its corresponding cell 1833 * -# go through every cell, check the atoms therein against all possible bond partners in the 27 adjacent cells, add bond if true 1834 * -# create the list of bonds via CreateListOfBondsPerAtom() 1835 * -# correct the bond degree iteratively (single->double->triple bond) 1836 * -# finally print the bond list to \a *out if desired 1837 1837 * \param *out out stream for printing the matrix, NULL if no output 1838 1838 * \param bonddistance length of linked cells (i.e. maximum minimal length checked) … … 1842 1842 { 1843 1843 1844 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;1845 int No, NoBonds, CandidateBondNo;1846 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;1847 molecule **CellList;1848 double distance, MinDistance, MaxDistance;1849 double *matrix = ReturnFullMatrixforSymmetric(cell_size);1850 Vector x;1851 int FalseBondDegree = 0;1852 1853 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem);1854 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl;1855 // remove every bond from the list1856 if ((first->next != last) && (last->previous != first)) {// there are bonds present1857 cleanup(first,last);1858 }1859 1860 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering)1861 CountAtoms(out);1862 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl;1863 1864 if (AtomCount != 0) {1865 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell1866 j=-1;1867 for (int i=0;i<NDIM;i++) {1868 j += i+1;1869 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance1870 //*out << Verbose(1) << "divisor[" << i << "]= " << divisor[i] << "." << endl;1871 }1872 // 2a. allocate memory for the cell list1873 NumberCells = divisor[0]*divisor[1]*divisor[2];1874 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl;1875 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList");1876 for (int i=NumberCells;i--;)1877 CellList[i] = NULL;1878 1879 // 2b. put all atoms into its corresponding list1880 Walker = start;1881 while(Walker->next != end) {1882 Walker = Walker->next;1883 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates ";1884 //Walker->x.Output(out);1885 //*out << "." << endl;1886 // compute the cell by the atom's coordinates1887 j=-1;1888 for (int i=0;i<NDIM;i++) {1889 j += i+1;1890 x.CopyVector(&(Walker->x));1891 x.KeepPeriodic(out, matrix);1892 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]);1893 }1894 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2];1895 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl;1896 // add copy atom to this cell1897 if (CellList[index] == NULL)// allocate molecule if not done1898 CellList[index] = new molecule(elemente);1899 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference1900 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl;1901 }1902 //for (int i=0;i<NumberCells;i++)1903 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl;1904 1905 1906 // 3a. go through every cell1907 for (N[0]=divisor[0];N[0]--;)1908 for (N[1]=divisor[1];N[1]--;)1909 for (N[2]=divisor[2];N[2]--;) {1910 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2];1911 if (CellList[Index] != NULL) { // if there atoms in this cell1912 //*out << Verbose(1) << "Current cell is " << Index << "." << endl;1913 // 3b. for every atom therein1914 Walker = CellList[Index]->start;1915 while (Walker->next != CellList[Index]->end) {// go through every atom1916 Walker = Walker->next;1917 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl;1918 // 3c. check for possible bond between each atom in this and every one in the 27 cells1919 for (n[0]=-1;n[0]<=1;n[0]++)1920 for (n[1]=-1;n[1]<=1;n[1]++)1921 for (n[2]=-1;n[2]<=1;n[2]++) {1922 // compute the index of this comparison cell and make it periodic1923 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];1924 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl;1925 if (CellList[index] != NULL) {// if there are any atoms in this cell1926 OtherWalker = CellList[index]->start;1927 while(OtherWalker->next != CellList[index]->end) {// go through every atom in this cell1928 OtherWalker = OtherWalker->next;1929 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl;1930 /// \todo periodic check is missing here!1931 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl;1932 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius;1933 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem;1934 MaxDistance = MinDistance + BONDTHRESHOLD;1935 MinDistance -= BONDTHRESHOLD;1936 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size);1937 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller1938 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl;1939 AddBond(Walker->father, OtherWalker->father, 1);// also increases molecule::BondCount1940 } else {1941 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl;1942 }1943 }1944 }1945 }1946 }1947 }1948 }1949 1950 1951 1952 // 4. free the cell again1953 for (int i=NumberCells;i--;)1954 if (CellList[i] != NULL) {1955 delete(CellList[i]);1956 }1957 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList");1958 1959 // create the adjacency list per atom1960 CreateListOfBondsPerAtom(out);1961 1962 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,1963 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene1964 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of1965 // double bonds as was expected.1966 if (BondCount != 0) {1967 NoCyclicBonds = 0;1968 *out << Verbose(1) << "Correcting Bond degree of each bond ... ";1969 do {1970 No = 0; // No acts as breakup flag (if 1 we still continue)1971 Walker = start;1972 while (Walker->next != end) { // go through every atom1973 Walker = Walker->next;1974 // count valence of first partner1975 NoBonds = 0;1976 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)1977 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;1978 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1979 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch1980 Candidate = NULL;1981 CandidateBondNo = -1;1982 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners1983 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);1984 // count valence of second partner1985 NoBonds = 0;1986 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)1987 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;1988 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;1989 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate1990 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first1991 Candidate = OtherWalker;1992 CandidateBondNo = i;1993 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;1994 }1995 }1996 }1997 if ((Candidate != NULL) && (CandidateBondNo != -1)) {1998 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;1999 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;2000 } else2001 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl;2002 FalseBondDegree++;2003 }2004 }2005 } while (No);2006 *out << " done." << endl;2007 } else2008 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl;2009 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl;2010 2011 // output bonds for debugging (if bond chain list was correctly installed)2012 *out << Verbose(1) << endl << "From contents of bond chain list:";2013 bond *Binder = first;2014 while(Binder->next != last) {2015 Binder = Binder->next;2016 *out << *Binder << "\t" << endl;2017 }2018 *out << endl;2019 } else2020 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl;2021 *out << Verbose(0) << "End of CreateAdjacencyList." << endl;2022 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix");1844 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1845 int No, NoBonds, CandidateBondNo; 1846 int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j; 1847 molecule **CellList; 1848 double distance, MinDistance, MaxDistance; 1849 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 1850 Vector x; 1851 int FalseBondDegree = 0; 1852 1853 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1854 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; 1855 // remove every bond from the list 1856 if ((first->next != last) && (last->previous != first)) { // there are bonds present 1857 cleanup(first,last); 1858 } 1859 1860 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1861 CountAtoms(out); 1862 *out << Verbose(1) << "AtomCount " << AtomCount << "." << endl; 1863 1864 if (AtomCount != 0) { 1865 // 1. find divisor for each axis, such that a sphere with radius of at least bonddistance can be placed into each cell 1866 j=-1; 1867 for (int i=0;i<NDIM;i++) { 1868 j += i+1; 1869 divisor[i] = (int)floor(cell_size[j]/bonddistance); // take smaller value such that size of linked cell is at least bonddistance 1870 //*out << Verbose(1) << "divisor[" << i << "] = " << divisor[i] << "." << endl; 1871 } 1872 // 2a. allocate memory for the cell list 1873 NumberCells = divisor[0]*divisor[1]*divisor[2]; 1874 *out << Verbose(1) << "Allocating " << NumberCells << " cells." << endl; 1875 CellList = (molecule **) Malloc(sizeof(molecule *)*NumberCells, "molecule::CreateAdjacencyList - ** CellList"); 1876 for (int i=NumberCells;i--;) 1877 CellList[i] = NULL; 1878 1879 // 2b. put all atoms into its corresponding list 1880 Walker = start; 1881 while(Walker->next != end) { 1882 Walker = Walker->next; 1883 //*out << Verbose(1) << "Current atom is " << *Walker << " with coordinates "; 1884 //Walker->x.Output(out); 1885 //*out << "." << endl; 1886 // compute the cell by the atom's coordinates 1887 j=-1; 1888 for (int i=0;i<NDIM;i++) { 1889 j += i+1; 1890 x.CopyVector(&(Walker->x)); 1891 x.KeepPeriodic(out, matrix); 1892 n[i] = (int)floor(x.x[i]/cell_size[j]*(double)divisor[i]); 1893 } 1894 index = n[2] + (n[1] + n[0] * divisor[1]) * divisor[2]; 1895 //*out << Verbose(1) << "Atom " << *Walker << " goes into cell number [" << n[0] << "," << n[1] << "," << n[2] << "] = " << index << "." << endl; 1896 // add copy atom to this cell 1897 if (CellList[index] == NULL) // allocate molecule if not done 1898 CellList[index] = new molecule(elemente); 1899 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1900 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1901 } 1902 //for (int i=0;i<NumberCells;i++) 1903 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1904 1905 1906 // 3a. go through every cell 1907 for (N[0]=divisor[0];N[0]--;) 1908 for (N[1]=divisor[1];N[1]--;) 1909 for (N[2]=divisor[2];N[2]--;) { 1910 Index = N[2] + (N[1] + N[0] * divisor[1]) * divisor[2]; 1911 if (CellList[Index] != NULL) { // if there atoms in this cell 1912 //*out << Verbose(1) << "Current cell is " << Index << "." << endl; 1913 // 3b. for every atom therein 1914 Walker = CellList[Index]->start; 1915 while (Walker->next != CellList[Index]->end) { // go through every atom 1916 Walker = Walker->next; 1917 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1918 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1919 for (n[0]=-1;n[0]<=1;n[0]++) 1920 for (n[1]=-1;n[1]<=1;n[1]++) 1921 for (n[2]=-1;n[2]<=1;n[2]++) { 1922 // compute the index of this comparison cell and make it periodic 1923 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]; 1924 //*out << Verbose(1) << "Number of comparison cell is " << index << "." << endl; 1925 if (CellList[index] != NULL) { // if there are any atoms in this cell 1926 OtherWalker = CellList[index]->start; 1927 while(OtherWalker->next != CellList[index]->end) { // go through every atom in this cell 1928 OtherWalker = OtherWalker->next; 1929 //*out << Verbose(0) << "Current comparison atom is " << *OtherWalker << "." << endl; 1930 /// \todo periodic check is missing here! 1931 //*out << Verbose(1) << "Checking distance " << OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size) << " against typical bond length of " << bonddistance*bonddistance << "." << endl; 1932 MinDistance = OtherWalker->type->CovalentRadius + Walker->type->CovalentRadius; 1933 MinDistance *= (IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem; 1934 MaxDistance = MinDistance + BONDTHRESHOLD; 1935 MinDistance -= BONDTHRESHOLD; 1936 distance = OtherWalker->x.PeriodicDistanceSquared(&(Walker->x), cell_size); 1937 if ((OtherWalker->father->nr > Walker->father->nr) && (distance <= MaxDistance*MaxDistance) && (distance >= MinDistance*MinDistance)) { // create bond if distance is smaller 1938 //*out << Verbose(1) << "Adding Bond between " << *Walker << " and " << *OtherWalker << " in distance " << sqrt(distance) << "." << endl; 1939 AddBond(Walker->father, OtherWalker->father, 1); // also increases molecule::BondCount 1940 } else { 1941 //*out << Verbose(1) << "Not Adding: Wrong label order or distance too great." << endl; 1942 } 1943 } 1944 } 1945 } 1946 } 1947 } 1948 } 1949 1950 1951 1952 // 4. free the cell again 1953 for (int i=NumberCells;i--;) 1954 if (CellList[i] != NULL) { 1955 delete(CellList[i]); 1956 } 1957 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1958 1959 // create the adjacency list per atom 1960 CreateListOfBondsPerAtom(out); 1961 1962 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1963 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene 1964 // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of 1965 // double bonds as was expected. 1966 if (BondCount != 0) { 1967 NoCyclicBonds = 0; 1968 *out << Verbose(1) << "Correcting Bond degree of each bond ... "; 1969 do { 1970 No = 0; // No acts as breakup flag (if 1 we still continue) 1971 Walker = start; 1972 while (Walker->next != end) { // go through every atom 1973 Walker = Walker->next; 1974 // count valence of first partner 1975 NoBonds = 0; 1976 for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) 1977 NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 1978 *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1979 if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch 1980 Candidate = NULL; 1981 CandidateBondNo = -1; 1982 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners 1983 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 1984 // count valence of second partner 1985 NoBonds = 0; 1986 for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++) 1987 NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree; 1988 *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl; 1989 if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate 1990 if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first 1991 Candidate = OtherWalker; 1992 CandidateBondNo = i; 1993 *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl; 1994 } 1995 } 1996 } 1997 if ((Candidate != NULL) && (CandidateBondNo != -1)) { 1998 ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++; 1999 *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl; 2000 } else 2001 *out << Verbose(2) << "Could not find correct degree for atom " << *Walker << "." << endl; 2002 FalseBondDegree++; 2003 } 2004 } 2005 } while (No); 2006 *out << " done." << endl; 2007 } else 2008 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 2009 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 2010 2011 // output bonds for debugging (if bond chain list was correctly installed) 2012 *out << Verbose(1) << endl << "From contents of bond chain list:"; 2013 bond *Binder = first; 2014 while(Binder->next != last) { 2015 Binder = Binder->next; 2016 *out << *Binder << "\t" << endl; 2017 } 2018 *out << endl; 2019 } else 2020 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 2021 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 2022 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 2023 2023 2024 2024 }; … … 2036 2036 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, class StackClass<bond *> *&BackEdgeStack) 2037 2037 { 2038 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);2039 BackEdgeStack = new StackClass<bond *> (BondCount);2040 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL);2041 MoleculeLeafClass *LeafWalker = SubGraphs;2042 int CurrentGraphNr = 0, OldGraphNr;2043 int ComponentNumber = 0;2044 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next;2045 bond *Binder = NULL;2046 bool BackStepping = false;2047 2048 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl;2049 2050 ResetAllBondsToUnused();2051 ResetAllAtomNumbers();2052 InitComponentNumbers();2053 BackEdgeStack->ClearStack();2054 while (Root != end) { // if there any atoms at all2055 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all2056 AtomStack->ClearStack();2057 2058 // put into new subgraph molecule and add this to list of subgraphs2059 LeafWalker = new MoleculeLeafClass(LeafWalker);2060 LeafWalker->Leaf = new molecule(elemente);2061 LeafWalker->Leaf->AddCopyAtom(Root);2062 2063 OldGraphNr = CurrentGraphNr;2064 Walker = Root;2065 do { // (10)2066 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom2067 if (!BackStepping) { // if we don't just return from (8)2068 Walker->GraphNr = CurrentGraphNr;2069 Walker->LowpointNr = CurrentGraphNr;2070 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl;2071 AtomStack->Push(Walker);2072 CurrentGraphNr++;2073 }2074 do { // (3) if Walker has no unused egdes, go to (5)2075 BackStepping = false; // reset backstepping flag for (8)2076 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused2077 Binder = FindNextUnused(Walker);2078 if (Binder == NULL)2079 break;2080 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl;2081 // (4) Mark Binder used, ...2082 Binder->MarkUsed(black);2083 OtherAtom = Binder->GetOtherAtom(Walker);2084 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl;2085 if (OtherAtom->GraphNr != -1) {2086 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3)2087 Binder->Type = BackEdge;2088 BackEdgeStack->Push(Binder);2089 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr;2090 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl;2091 } else {2092 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2)2093 Binder->Type = TreeEdge;2094 OtherAtom->Ancestor = Walker;2095 Walker = OtherAtom;2096 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl;2097 break;2098 }2099 Binder = NULL;2100 } while (1);// (3)2101 if (Binder == NULL) {2102 *out << Verbose(2) << "No more Unused Bonds." << endl;2103 break;2104 } else2105 Binder = NULL;2106 } while (1);// (2)2107 2108 // 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!2109 if ((Walker == Root) && (Binder == NULL))2110 break;2111 2112 // (5) if Ancestor of Walker is ...2113 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl;2114 if (Walker->Ancestor->GraphNr != Root->GraphNr) {2115 // (6)(Ancestor of Walker is not Root)2116 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) {2117 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8)2118 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr;2119 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl;2120 } else {2121 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component2122 Walker->Ancestor->SeparationVertex = true;2123 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl;2124 SetNextComponentNumber(Walker->Ancestor, ComponentNumber);2125 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl;2126 SetNextComponentNumber(Walker, ComponentNumber);2127 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl;2128 do {2129 OtherAtom = AtomStack->PopLast();2130 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2131 SetNextComponentNumber(OtherAtom, ComponentNumber);2132 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2133 } while (OtherAtom != Walker);2134 ComponentNumber++;2135 }2136 // (8) Walker becomes its Ancestor, go to (3)2137 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl;2138 Walker = Walker->Ancestor;2139 BackStepping = true;2140 }2141 if (!BackStepping) {// coming from (8) want to go to (3)2142 // (9) remove all from stack till Walker (including), these and Root form a component2143 AtomStack->Output(out);2144 SetNextComponentNumber(Root, ComponentNumber);2145 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl;2146 SetNextComponentNumber(Walker, ComponentNumber);2147 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl;2148 do {2149 OtherAtom = AtomStack->PopLast();2150 LeafWalker->Leaf->AddCopyAtom(OtherAtom);2151 SetNextComponentNumber(OtherAtom, ComponentNumber);2152 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl;2153 } while (OtherAtom != Walker);2154 ComponentNumber++;2155 2156 // (11) Root is separation vertex,set Walker to Root and go to (4)2157 Walker = Root;2158 Binder = FindNextUnused(Walker);2159 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl;2160 if (Binder != NULL) { // Root is separation vertex2161 *out << Verbose(1) << "(11) Root is a separation vertex." << endl;2162 Walker->SeparationVertex = true;2163 }2164 }2165 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges2166 2167 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph2168 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl;2169 LeafWalker->Leaf->Output(out);2170 *out << endl;2171 2172 // step on to next root2173 while ((Root != end) && (Root->GraphNr != -1)) {2174 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl;2175 if (Root->GraphNr != -1) // if already discovered, step on2176 Root = Root->next;2177 }2178 }2179 // set cyclic bond criterium on "same LP" basis2180 Binder = first;2181 while(Binder->next != last) {2182 Binder = Binder->next;2183 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ??2184 Binder->Cyclic = true;2185 NoCyclicBonds++;2186 }2187 }2188 2189 2190 *out << Verbose(1) << "Final graph info for each atom is:" << endl;2191 Walker = start;2192 while (Walker->next != end) {2193 Walker = Walker->next;2194 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are ";2195 OutputComponentNumber(out, Walker);2196 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl;2197 }2198 2199 *out << Verbose(1) << "Final graph info for each bond is:" << endl;2200 Binder = first;2201 while(Binder->next != last) {2202 Binder = Binder->next;2203 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <";2204 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp.";2205 OutputComponentNumber(out, Binder->leftatom);2206 *out << " ===";2207 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp.";2208 OutputComponentNumber(out, Binder->rightatom);2209 *out << ">." << endl;2210 if (Binder->Cyclic) // cyclic ??2211 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl;2212 }2213 2214 // free all and exit2215 delete(AtomStack);2216 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl;2217 return SubGraphs;2038 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 2039 BackEdgeStack = new StackClass<bond *> (BondCount); 2040 MoleculeLeafClass *SubGraphs = new MoleculeLeafClass(NULL); 2041 MoleculeLeafClass *LeafWalker = SubGraphs; 2042 int CurrentGraphNr = 0, OldGraphNr; 2043 int ComponentNumber = 0; 2044 atom *Walker = NULL, *OtherAtom = NULL, *Root = start->next; 2045 bond *Binder = NULL; 2046 bool BackStepping = false; 2047 2048 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 2049 2050 ResetAllBondsToUnused(); 2051 ResetAllAtomNumbers(); 2052 InitComponentNumbers(); 2053 BackEdgeStack->ClearStack(); 2054 while (Root != end) { // if there any atoms at all 2055 // (1) mark all edges unused, empty stack, set atom->GraphNr = 0 for all 2056 AtomStack->ClearStack(); 2057 2058 // put into new subgraph molecule and add this to list of subgraphs 2059 LeafWalker = new MoleculeLeafClass(LeafWalker); 2060 LeafWalker->Leaf = new molecule(elemente); 2061 LeafWalker->Leaf->AddCopyAtom(Root); 2062 2063 OldGraphNr = CurrentGraphNr; 2064 Walker = Root; 2065 do { // (10) 2066 do { // (2) set number and Lowpoint of Atom to i, increase i, push current atom 2067 if (!BackStepping) { // if we don't just return from (8) 2068 Walker->GraphNr = CurrentGraphNr; 2069 Walker->LowpointNr = CurrentGraphNr; 2070 *out << Verbose(1) << "Setting Walker[" << Walker->Name << "]'s number to " << Walker->GraphNr << " with Lowpoint " << Walker->LowpointNr << "." << endl; 2071 AtomStack->Push(Walker); 2072 CurrentGraphNr++; 2073 } 2074 do { // (3) if Walker has no unused egdes, go to (5) 2075 BackStepping = false; // reset backstepping flag for (8) 2076 if (Binder == NULL) // if we don't just return from (11), Binder is already set to next unused 2077 Binder = FindNextUnused(Walker); 2078 if (Binder == NULL) 2079 break; 2080 *out << Verbose(2) << "Current Unused Bond is " << *Binder << "." << endl; 2081 // (4) Mark Binder used, ... 2082 Binder->MarkUsed(black); 2083 OtherAtom = Binder->GetOtherAtom(Walker); 2084 *out << Verbose(2) << "(4) OtherAtom is " << OtherAtom->Name << "." << endl; 2085 if (OtherAtom->GraphNr != -1) { 2086 // (4a) ... if "other" atom has been visited (GraphNr != 0), set lowpoint to minimum of both, go to (3) 2087 Binder->Type = BackEdge; 2088 BackEdgeStack->Push(Binder); 2089 Walker->LowpointNr = ( Walker->LowpointNr < OtherAtom->GraphNr ) ? Walker->LowpointNr : OtherAtom->GraphNr; 2090 *out << Verbose(3) << "(4a) Visited: Setting Lowpoint of Walker[" << Walker->Name << "] to " << Walker->LowpointNr << "." << endl; 2091 } else { 2092 // (4b) ... otherwise set OtherAtom as Ancestor of Walker and Walker as OtherAtom, go to (2) 2093 Binder->Type = TreeEdge; 2094 OtherAtom->Ancestor = Walker; 2095 Walker = OtherAtom; 2096 *out << Verbose(3) << "(4b) Not Visited: OtherAtom[" << OtherAtom->Name << "]'s Ancestor is now " << OtherAtom->Ancestor->Name << ", Walker is OtherAtom " << OtherAtom->Name << "." << endl; 2097 break; 2098 } 2099 Binder = NULL; 2100 } while (1); // (3) 2101 if (Binder == NULL) { 2102 *out << Verbose(2) << "No more Unused Bonds." << endl; 2103 break; 2104 } else 2105 Binder = NULL; 2106 } while (1); // (2) 2107 2108 // 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! 2109 if ((Walker == Root) && (Binder == NULL)) 2110 break; 2111 2112 // (5) if Ancestor of Walker is ... 2113 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 2114 if (Walker->Ancestor->GraphNr != Root->GraphNr) { 2115 // (6) (Ancestor of Walker is not Root) 2116 if (Walker->LowpointNr < Walker->Ancestor->GraphNr) { 2117 // (6a) set Ancestor's Lowpoint number to minimum of of its Ancestor and itself, go to Step(8) 2118 Walker->Ancestor->LowpointNr = (Walker->Ancestor->LowpointNr < Walker->LowpointNr) ? Walker->Ancestor->LowpointNr : Walker->LowpointNr; 2119 *out << Verbose(2) << "(6) Setting Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s Lowpoint to " << Walker->Ancestor->LowpointNr << "." << endl; 2120 } else { 2121 // (7) (Ancestor of Walker is a separating vertex, remove all from stack till Walker (including), these and Ancestor form a component 2122 Walker->Ancestor->SeparationVertex = true; 2123 *out << Verbose(2) << "(7) Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "]'s is a separating vertex, creating component." << endl; 2124 SetNextComponentNumber(Walker->Ancestor, ComponentNumber); 2125 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Ancestor's Compont is " << ComponentNumber << "." << endl; 2126 SetNextComponentNumber(Walker, ComponentNumber); 2127 *out << Verbose(3) << "(7) Walker[" << Walker->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2128 do { 2129 OtherAtom = AtomStack->PopLast(); 2130 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2131 SetNextComponentNumber(OtherAtom, ComponentNumber); 2132 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2133 } while (OtherAtom != Walker); 2134 ComponentNumber++; 2135 } 2136 // (8) Walker becomes its Ancestor, go to (3) 2137 *out << Verbose(2) << "(8) Walker[" << Walker->Name << "] is now its Ancestor " << Walker->Ancestor->Name << ", backstepping. " << endl; 2138 Walker = Walker->Ancestor; 2139 BackStepping = true; 2140 } 2141 if (!BackStepping) { // coming from (8) want to go to (3) 2142 // (9) remove all from stack till Walker (including), these and Root form a component 2143 AtomStack->Output(out); 2144 SetNextComponentNumber(Root, ComponentNumber); 2145 *out << Verbose(3) << "(9) Root[" << Root->Name << "]'s Component is " << ComponentNumber << "." << endl; 2146 SetNextComponentNumber(Walker, ComponentNumber); 2147 *out << Verbose(3) << "(9) Walker[" << Walker->Name << "]'s Component is " << ComponentNumber << "." << endl; 2148 do { 2149 OtherAtom = AtomStack->PopLast(); 2150 LeafWalker->Leaf->AddCopyAtom(OtherAtom); 2151 SetNextComponentNumber(OtherAtom, ComponentNumber); 2152 *out << Verbose(3) << "(7) Other[" << OtherAtom->Name << "]'s Compont is " << ComponentNumber << "." << endl; 2153 } while (OtherAtom != Walker); 2154 ComponentNumber++; 2155 2156 // (11) Root is separation vertex, set Walker to Root and go to (4) 2157 Walker = Root; 2158 Binder = FindNextUnused(Walker); 2159 *out << Verbose(1) << "(10) Walker is Root[" << Root->Name << "], next Unused Bond is " << Binder << "." << endl; 2160 if (Binder != NULL) { // Root is separation vertex 2161 *out << Verbose(1) << "(11) Root is a separation vertex." << endl; 2162 Walker->SeparationVertex = true; 2163 } 2164 } 2165 } while ((BackStepping) || (Binder != NULL)); // (10) halt only if Root has no unused edges 2166 2167 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2168 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2169 LeafWalker->Leaf->Output(out); 2170 *out << endl; 2171 2172 // step on to next root 2173 while ((Root != end) && (Root->GraphNr != -1)) { 2174 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2175 if (Root->GraphNr != -1) // if already discovered, step on 2176 Root = Root->next; 2177 } 2178 } 2179 // set cyclic bond criterium on "same LP" basis 2180 Binder = first; 2181 while(Binder->next != last) { 2182 Binder = Binder->next; 2183 if (Binder->rightatom->LowpointNr == Binder->leftatom->LowpointNr) { // cyclic ?? 2184 Binder->Cyclic = true; 2185 NoCyclicBonds++; 2186 } 2187 } 2188 2189 2190 *out << Verbose(1) << "Final graph info for each atom is:" << endl; 2191 Walker = start; 2192 while (Walker->next != end) { 2193 Walker = Walker->next; 2194 *out << Verbose(2) << "Atom " << Walker->Name << " is " << ((Walker->SeparationVertex) ? "a" : "not a") << " separation vertex, components are "; 2195 OutputComponentNumber(out, Walker); 2196 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2197 } 2198 2199 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2200 Binder = first; 2201 while(Binder->next != last) { 2202 Binder = Binder->next; 2203 *out << Verbose(2) << ((Binder->Type == TreeEdge) ? "TreeEdge " : "BackEdge ") << *Binder << ": <"; 2204 *out << ((Binder->leftatom->SeparationVertex) ? "SP," : "") << "L" << Binder->leftatom->LowpointNr << " G" << Binder->leftatom->GraphNr << " Comp."; 2205 OutputComponentNumber(out, Binder->leftatom); 2206 *out << " === "; 2207 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2208 OutputComponentNumber(out, Binder->rightatom); 2209 *out << ">." << endl; 2210 if (Binder->Cyclic) // cyclic ?? 2211 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; 2212 } 2213 2214 // free all and exit 2215 delete(AtomStack); 2216 *out << Verbose(0) << "End of DepthFirstSearchAnalysis" << endl; 2217 return SubGraphs; 2218 2218 }; 2219 2219 … … 2228 2228 * \todo BFS from the not-same-LP to find back to starting point of tributary cycle over more than one bond 2229 2229 */ 2230 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize)2231 { 2232 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList");2233 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList");2234 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");2235 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);// will hold the current ring2236 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);// contains all "touched" atoms (that need to be reset after BFS loop)2237 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;2238 bond *Binder = NULL, *BackEdge = NULL;2239 int RingSize, NumCycles, MinRingSize = -1;2240 2241 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray2242 for (int i=AtomCount;i--;) {2243 PredecessorList[i] = NULL;2244 ShortestPathList[i] = -1;2245 ColorList[i] = white;2246 }2247 2248 *out << Verbose(1) << "Back edge list - ";2249 BackEdgeStack->Output(out);2250 2251 *out << Verbose(1) << "Analysing cycles ... " << endl;2252 NumCycles = 0;2253 while (!BackEdgeStack->IsEmpty()) {2254 BackEdge = BackEdgeStack->PopFirst();2255 // this is the target2256 Root = BackEdge->leftatom;2257 // this is the source point2258 Walker = BackEdge->rightatom;2259 ShortestPathList[Walker->nr] = 0;2260 BFSStack->ClearStack();// start with empty BFS stack2261 BFSStack->Push(Walker);2262 TouchedStack->Push(Walker);2263 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2264 OtherAtom = NULL;2265 do {// look for Root2266 Walker = BFSStack->PopFirst();2267 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2268 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2269 Binder = ListOfBondsPerAtom[Walker->nr][i];2270 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)2271 OtherAtom = Binder->GetOtherAtom(Walker);2230 void molecule::CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> * BackEdgeStack, int *&MinimumRingSize) 2231 { 2232 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2233 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2234 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2235 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2236 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2237 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; 2238 bond *Binder = NULL, *BackEdge = NULL; 2239 int RingSize, NumCycles, MinRingSize = -1; 2240 2241 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 2242 for (int i=AtomCount;i--;) { 2243 PredecessorList[i] = NULL; 2244 ShortestPathList[i] = -1; 2245 ColorList[i] = white; 2246 } 2247 2248 *out << Verbose(1) << "Back edge list - "; 2249 BackEdgeStack->Output(out); 2250 2251 *out << Verbose(1) << "Analysing cycles ... " << endl; 2252 NumCycles = 0; 2253 while (!BackEdgeStack->IsEmpty()) { 2254 BackEdge = BackEdgeStack->PopFirst(); 2255 // this is the target 2256 Root = BackEdge->leftatom; 2257 // this is the source point 2258 Walker = BackEdge->rightatom; 2259 ShortestPathList[Walker->nr] = 0; 2260 BFSStack->ClearStack(); // start with empty BFS stack 2261 BFSStack->Push(Walker); 2262 TouchedStack->Push(Walker); 2263 *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2264 OtherAtom = NULL; 2265 do { // look for Root 2266 Walker = BFSStack->PopFirst(); 2267 *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2268 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2269 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2270 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2271 OtherAtom = Binder->GetOtherAtom(Walker); 2272 2272 #ifdef ADDHYDROGEN 2273 if (OtherAtom->type->Z != 1) {2273 if (OtherAtom->type->Z != 1) { 2274 2274 #endif 2275 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2276 if (ColorList[OtherAtom->nr] == white) {2277 TouchedStack->Push(OtherAtom);2278 ColorList[OtherAtom->nr] = lightgray;2279 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2280 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2281 *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;2282 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance2283 *out << Verbose(3) << "Putting OtherAtom into queue." << endl;2284 BFSStack->Push(OtherAtom);2285 //}2286 } else {2287 *out << Verbose(3) << "Not Adding, has already been visited." << endl;2288 }2289 if (OtherAtom == Root)2290 break;2275 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2276 if (ColorList[OtherAtom->nr] == white) { 2277 TouchedStack->Push(OtherAtom); 2278 ColorList[OtherAtom->nr] = lightgray; 2279 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2280 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2281 *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; 2282 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2283 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; 2284 BFSStack->Push(OtherAtom); 2285 //} 2286 } else { 2287 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 2288 } 2289 if (OtherAtom == Root) 2290 break; 2291 2291 #ifdef ADDHYDROGEN 2292 } else {2293 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;2294 ColorList[OtherAtom->nr] = black;2295 }2292 } else { 2293 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; 2294 ColorList[OtherAtom->nr] = black; 2295 } 2296 2296 #endif 2297 } else {2298 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;2299 }2300 }2301 ColorList[Walker->nr] = black;2302 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2303 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand2304 // step through predecessor list2305 while (OtherAtom != BackEdge->rightatom) {2306 if (!OtherAtom->GetTrueFather()->IsCyclic)// if one bond in the loop is not marked as cyclic, we haven't found this cycle yet2307 break;2308 else2309 OtherAtom = PredecessorList[OtherAtom->nr];2310 }2311 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already2312 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\2313 do {2314 OtherAtom = TouchedStack->PopLast();2315 if (PredecessorList[OtherAtom->nr] == Walker) {2316 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;2317 PredecessorList[OtherAtom->nr] = NULL;2318 ShortestPathList[OtherAtom->nr] = -1;2319 ColorList[OtherAtom->nr] = white;2320 BFSStack->RemoveItem(OtherAtom);2321 }2322 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));2323 TouchedStack->Push(OtherAtom);// last was wrongly popped2324 OtherAtom = BackEdge->rightatom; // set to not Root2325 } else2326 OtherAtom = Root;2327 }2328 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));2329 2330 if (OtherAtom == Root) {2331 // now climb back the predecessor list and thus find the cycle members2332 NumCycles++;2333 RingSize = 1;2334 Root->GetTrueFather()->IsCyclic = true;2335 *out << Verbose(1) << "Found ring contains: ";2336 Walker = Root;2337 while (Walker != BackEdge->rightatom) {2338 *out << Walker->Name << " <-> ";2339 Walker = PredecessorList[Walker->nr];2340 Walker->GetTrueFather()->IsCyclic = true;2341 RingSize++;2342 }2343 *out << Walker->Name << "with a length of " << RingSize << "." << endl << endl;2344 // walk through all and set MinimumRingSize2345 Walker = Root;2346 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2347 while (Walker != BackEdge->rightatom) {2348 Walker = PredecessorList[Walker->nr];2349 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr])2350 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize;2351 }2352 if ((RingSize < MinRingSize) || (MinRingSize == -1))2353 MinRingSize = RingSize;2354 } else {2355 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl;2356 }2357 2358 // now clean the lists2359 while (!TouchedStack->IsEmpty()){2360 Walker = TouchedStack->PopFirst();2361 PredecessorList[Walker->nr] = NULL;2362 ShortestPathList[Walker->nr] = -1;2363 ColorList[Walker->nr] = white;2364 }2365 }2366 if (MinRingSize != -1) {2367 // go over all atoms2368 Root = start;2369 while(Root->next != end) {2370 Root = Root->next;2371 2372 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is2373 Walker = Root;2374 ShortestPathList[Walker->nr] = 0;2375 BFSStack->ClearStack();// start with empty BFS stack2376 BFSStack->Push(Walker);2377 TouchedStack->Push(Walker);2378 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;2379 OtherAtom = Walker;2380 while (OtherAtom != NULL) {// look for Root2381 Walker = BFSStack->PopFirst();2382 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;2383 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {2384 Binder = ListOfBondsPerAtom[Walker->nr][i];2385 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 check2386 OtherAtom = Binder->GetOtherAtom(Walker);2387 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;2388 if (ColorList[OtherAtom->nr] == white) {2389 TouchedStack->Push(OtherAtom);2390 ColorList[OtherAtom->nr] = lightgray;2391 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor2392 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;2393 //*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;2394 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring2395 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr];2396 OtherAtom = NULL; //break;2397 break;2398 } else2399 BFSStack->Push(OtherAtom);2400 } else {2401 //*out << Verbose(3) << "Not Adding, has already been visited." << endl;2402 }2403 } else {2404 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;2405 }2406 }2407 ColorList[Walker->nr] = black;2408 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;2409 }2410 2411 // now clean the lists2412 while (!TouchedStack->IsEmpty()){2413 Walker = TouchedStack->PopFirst();2414 PredecessorList[Walker->nr] = NULL;2415 ShortestPathList[Walker->nr] = -1;2416 ColorList[Walker->nr] = white;2417 }2418 }2419 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl;2420 }2421 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl;2422 } else2423 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl;2424 2425 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList");2426 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList");2427 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList");2428 delete(BFSStack);2297 } else { 2298 *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl; 2299 } 2300 } 2301 ColorList[Walker->nr] = black; 2302 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2303 if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand 2304 // step through predecessor list 2305 while (OtherAtom != BackEdge->rightatom) { 2306 if (!OtherAtom->GetTrueFather()->IsCyclic) // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet 2307 break; 2308 else 2309 OtherAtom = PredecessorList[OtherAtom->nr]; 2310 } 2311 if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already 2312 *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\ 2313 do { 2314 OtherAtom = TouchedStack->PopLast(); 2315 if (PredecessorList[OtherAtom->nr] == Walker) { 2316 *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl; 2317 PredecessorList[OtherAtom->nr] = NULL; 2318 ShortestPathList[OtherAtom->nr] = -1; 2319 ColorList[OtherAtom->nr] = white; 2320 BFSStack->RemoveItem(OtherAtom); 2321 } 2322 } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL)); 2323 TouchedStack->Push(OtherAtom); // last was wrongly popped 2324 OtherAtom = BackEdge->rightatom; // set to not Root 2325 } else 2326 OtherAtom = Root; 2327 } 2328 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2329 2330 if (OtherAtom == Root) { 2331 // now climb back the predecessor list and thus find the cycle members 2332 NumCycles++; 2333 RingSize = 1; 2334 Root->GetTrueFather()->IsCyclic = true; 2335 *out << Verbose(1) << "Found ring contains: "; 2336 Walker = Root; 2337 while (Walker != BackEdge->rightatom) { 2338 *out << Walker->Name << " <-> "; 2339 Walker = PredecessorList[Walker->nr]; 2340 Walker->GetTrueFather()->IsCyclic = true; 2341 RingSize++; 2342 } 2343 *out << Walker->Name << " with a length of " << RingSize << "." << endl << endl; 2344 // walk through all and set MinimumRingSize 2345 Walker = Root; 2346 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2347 while (Walker != BackEdge->rightatom) { 2348 Walker = PredecessorList[Walker->nr]; 2349 if (RingSize < MinimumRingSize[Walker->GetTrueFather()->nr]) 2350 MinimumRingSize[Walker->GetTrueFather()->nr] = RingSize; 2351 } 2352 if ((RingSize < MinRingSize) || (MinRingSize == -1)) 2353 MinRingSize = RingSize; 2354 } else { 2355 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2356 } 2357 2358 // now clean the lists 2359 while (!TouchedStack->IsEmpty()){ 2360 Walker = TouchedStack->PopFirst(); 2361 PredecessorList[Walker->nr] = NULL; 2362 ShortestPathList[Walker->nr] = -1; 2363 ColorList[Walker->nr] = white; 2364 } 2365 } 2366 if (MinRingSize != -1) { 2367 // go over all atoms 2368 Root = start; 2369 while(Root->next != end) { 2370 Root = Root->next; 2371 2372 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2373 Walker = Root; 2374 ShortestPathList[Walker->nr] = 0; 2375 BFSStack->ClearStack(); // start with empty BFS stack 2376 BFSStack->Push(Walker); 2377 TouchedStack->Push(Walker); 2378 //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl; 2379 OtherAtom = Walker; 2380 while (OtherAtom != NULL) { // look for Root 2381 Walker = BFSStack->PopFirst(); 2382 //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl; 2383 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 2384 Binder = ListOfBondsPerAtom[Walker->nr][i]; 2385 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 2386 OtherAtom = Binder->GetOtherAtom(Walker); 2387 //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 2388 if (ColorList[OtherAtom->nr] == white) { 2389 TouchedStack->Push(OtherAtom); 2390 ColorList[OtherAtom->nr] = lightgray; 2391 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2392 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2393 //*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; 2394 if (OtherAtom->GetTrueFather()->IsCyclic) { // if the other atom is connected to a ring 2395 MinimumRingSize[Root->GetTrueFather()->nr] = ShortestPathList[OtherAtom->nr]+MinimumRingSize[OtherAtom->GetTrueFather()->nr]; 2396 OtherAtom = NULL; //break; 2397 break; 2398 } else 2399 BFSStack->Push(OtherAtom); 2400 } else { 2401 //*out << Verbose(3) << "Not Adding, has already been visited." << endl; 2402 } 2403 } else { 2404 //*out << Verbose(3) << "Not Visiting, is a back edge." << endl; 2405 } 2406 } 2407 ColorList[Walker->nr] = black; 2408 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2409 } 2410 2411 // now clean the lists 2412 while (!TouchedStack->IsEmpty()){ 2413 Walker = TouchedStack->PopFirst(); 2414 PredecessorList[Walker->nr] = NULL; 2415 ShortestPathList[Walker->nr] = -1; 2416 ColorList[Walker->nr] = white; 2417 } 2418 } 2419 *out << Verbose(1) << "Minimum ring size of " << *Root << " is " << MinimumRingSize[Root->GetTrueFather()->nr] << "." << endl; 2420 } 2421 *out << Verbose(1) << "Minimum ring size is " << MinRingSize << ", over " << NumCycles << " cycles total." << endl; 2422 } else 2423 *out << Verbose(1) << "No rings were detected in the molecular structure." << endl; 2424 2425 Free((void **)&PredecessorList, "molecule::CyclicStructureAnalysis: **PredecessorList"); 2426 Free((void **)&ShortestPathList, "molecule::CyclicStructureAnalysis: **ShortestPathList"); 2427 Free((void **)&ColorList, "molecule::CyclicStructureAnalysis: **ColorList"); 2428 delete(BFSStack); 2429 2429 }; 2430 2430 … … 2436 2436 void molecule::SetNextComponentNumber(atom *vertex, int nr) 2437 2437 { 2438 int i=0;2439 if (vertex != NULL) {2440 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) {2441 if (vertex->ComponentNr[i] == -1) {// check if not yet used2442 vertex->ComponentNr[i] = nr;2443 break;2444 }2445 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time2446 break;// breaking here will not cause error!2447 }2448 if (i == NumberOfBondsPerAtom[vertex->nr])2449 cerr << "Error: All Component entries are already occupied!" << endl;2450 } else2451 cerr << "Error: Given vertex is NULL!" << endl;2438 int i=0; 2439 if (vertex != NULL) { 2440 for(;i<NumberOfBondsPerAtom[vertex->nr];i++) { 2441 if (vertex->ComponentNr[i] == -1) { // check if not yet used 2442 vertex->ComponentNr[i] = nr; 2443 break; 2444 } 2445 else if (vertex->ComponentNr[i] == nr) // if number is already present, don't add another time 2446 break; // breaking here will not cause error! 2447 } 2448 if (i == NumberOfBondsPerAtom[vertex->nr]) 2449 cerr << "Error: All Component entries are already occupied!" << endl; 2450 } else 2451 cerr << "Error: Given vertex is NULL!" << endl; 2452 2452 }; 2453 2453 … … 2457 2457 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2458 2458 { 2459 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2460 *out << vertex->ComponentNr[i] << "";2459 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2460 *out << vertex->ComponentNr[i] << " "; 2461 2461 }; 2462 2462 … … 2465 2465 void molecule::InitComponentNumbers() 2466 2466 { 2467 atom *Walker = start;2468 while(Walker->next != end) {2469 Walker = Walker->next;2470 if (Walker->ComponentNr != NULL)2471 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr");2472 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr");2473 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;)2474 Walker->ComponentNr[i] = -1;2475 }2467 atom *Walker = start; 2468 while(Walker->next != end) { 2469 Walker = Walker->next; 2470 if (Walker->ComponentNr != NULL) 2471 Free((void **)&Walker->ComponentNr, "molecule::InitComponentNumbers: **Walker->ComponentNr"); 2472 Walker->ComponentNr = (int *) Malloc(sizeof(int)*NumberOfBondsPerAtom[Walker->nr], "molecule::InitComponentNumbers: *Walker->ComponentNr"); 2473 for (int i=NumberOfBondsPerAtom[Walker->nr];i--;) 2474 Walker->ComponentNr[i] = -1; 2475 } 2476 2476 }; 2477 2477 … … 2482 2482 bond * molecule::FindNextUnused(atom *vertex) 2483 2483 { 2484 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++)2485 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white)2486 return(ListOfBondsPerAtom[vertex->nr][i]);2487 return NULL;2484 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2485 if (ListOfBondsPerAtom[vertex->nr][i]->IsUsed() == white) 2486 return(ListOfBondsPerAtom[vertex->nr][i]); 2487 return NULL; 2488 2488 }; 2489 2489 … … 2493 2493 void molecule::ResetAllBondsToUnused() 2494 2494 { 2495 bond *Binder = first;2496 while (Binder->next != last) {2497 Binder = Binder->next;2498 Binder->ResetUsed();2499 }2495 bond *Binder = first; 2496 while (Binder->next != last) { 2497 Binder = Binder->next; 2498 Binder->ResetUsed(); 2499 } 2500 2500 }; 2501 2501 … … 2504 2504 void molecule::ResetAllAtomNumbers() 2505 2505 { 2506 atom *Walker = start;2507 while (Walker->next != end) {2508 Walker = Walker->next;2509 Walker->GraphNr= -1;2510 }2506 atom *Walker = start; 2507 while (Walker->next != end) { 2508 Walker = Walker->next; 2509 Walker->GraphNr = -1; 2510 } 2511 2511 }; 2512 2512 … … 2517 2517 void OutputAlreadyVisited(ofstream *out, int *list) 2518 2518 { 2519 *out << Verbose(4) << "Already Visited Bonds:\t";2520 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << "";2521 *out << endl;2519 *out << Verbose(4) << "Already Visited Bonds:\t"; 2520 for(int i=1;i<=list[0];i++) *out << Verbose(0) << list[i] << " "; 2521 *out << endl; 2522 2522 }; 2523 2523 … … 2525 2525 * The upper limit is 2526 2526 * \f[ 2527 * n = N \cdot C^k2527 * n = N \cdot C^k 2528 2528 * \f] 2529 2529 * where \f$C=2^c\f$ and c is the maximum bond degree over N number of atoms. … … 2534 2534 int molecule::GuesstimateFragmentCount(ofstream *out, int order) 2535 2535 { 2536 int c = 0;2537 int FragmentCount;2538 // get maximum bond degree2539 atom *Walker = start;2540 while (Walker->next != end) {2541 Walker = Walker->next;2542 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c;2543 }2544 FragmentCount = NoNonHydrogen*(1 << (c*order));2545 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl;2546 return FragmentCount;2536 int c = 0; 2537 int FragmentCount; 2538 // get maximum bond degree 2539 atom *Walker = start; 2540 while (Walker->next != end) { 2541 Walker = Walker->next; 2542 c = (NumberOfBondsPerAtom[Walker->nr] > c) ? NumberOfBondsPerAtom[Walker->nr] : c; 2543 } 2544 FragmentCount = NoNonHydrogen*(1 << (c*order)); 2545 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2546 return FragmentCount; 2547 2547 }; 2548 2548 … … 2555 2555 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 2556 2556 { 2557 stringstream line;2558 int AtomNr;2559 int status = 0;2560 2561 line.str(buffer);2562 while (!line.eof()) {2563 line >> AtomNr;2564 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2565 CurrentSet.insert(AtomNr);// insert at end, hence in same order as in file!2566 status++;2567 } // else it's "-1" or else and thus must not be added2568 }2569 *out << Verbose(1) << "The scanned KeySet is ";2570 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) {2571 *out << (*runner) << "\t";2572 }2573 *out << endl;2574 return (status != 0);2557 stringstream line; 2558 int AtomNr; 2559 int status = 0; 2560 2561 line.str(buffer); 2562 while (!line.eof()) { 2563 line >> AtomNr; 2564 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2565 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 2566 status++; 2567 } // else it's "-1" or else and thus must not be added 2568 } 2569 *out << Verbose(1) << "The scanned KeySet is "; 2570 for(KeySet::iterator runner = CurrentSet.begin(); runner != CurrentSet.end(); runner++) { 2571 *out << (*runner) << "\t"; 2572 } 2573 *out << endl; 2574 return (status != 0); 2575 2575 }; 2576 2576 … … 2587 2587 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 2588 2588 { 2589 bool status = true;2590 ifstream InputFile;2591 stringstream line;2592 GraphTestPair testGraphInsert;2593 int NumberOfFragments = 0;2594 double TEFactor;2595 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");2596 2597 if (FragmentList == NULL) { // check list pointer2598 FragmentList = new Graph;2599 }2600 2601 // 1st pass: open file and read2602 *out << Verbose(1) << "Parsing the KeySet file ... " << endl;2603 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE);2604 InputFile.open(filename);2605 if (InputFile != NULL) {2606 // each line represents a new fragment2607 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer");2608 // 1. parse keysets and insert into temp. graph2609 while (!InputFile.eof()) {2610 InputFile.getline(buffer, MAXSTRINGSIZE);2611 KeySet CurrentSet;2612 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) {// if at least one valid atom was added, write config2613 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1)));// store fragment number and current factor2614 if (!testGraphInsert.second) {2615 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl;2616 }2617 }2618 }2619 // 2. Free and done2620 InputFile.close();2621 InputFile.clear();2622 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer");2623 *out << Verbose(1) << "done." << endl;2624 } else {2625 *out << Verbose(1) << "File " << filename << " not found." << endl;2626 status = false;2627 }2628 2629 // 2nd pass: open TEFactors file and read2630 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;2631 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE);2632 InputFile.open(filename);2633 if (InputFile != NULL) {2634 // 3. add found TEFactors to each keyset2635 NumberOfFragments = 0;2636 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) {2637 if (!InputFile.eof()) {2638 InputFile >> TEFactor;2639 (*runner).second.second = TEFactor;2640 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl;2641 } else {2642 status = false;2643 break;2644 }2645 }2646 // 4. Free and done2647 InputFile.close();2648 *out << Verbose(1) << "done." << endl;2649 } else {2650 *out << Verbose(1) << "File " << filename << " not found." << endl;2651 status = false;2652 }2653 2654 // free memory2655 Free((void **)&filename, "molecule::ParseKeySetFile - filename");2656 2657 return status;2589 bool status = true; 2590 ifstream InputFile; 2591 stringstream line; 2592 GraphTestPair testGraphInsert; 2593 int NumberOfFragments = 0; 2594 double TEFactor; 2595 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2596 2597 if (FragmentList == NULL) { // check list pointer 2598 FragmentList = new Graph; 2599 } 2600 2601 // 1st pass: open file and read 2602 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; 2603 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); 2604 InputFile.open(filename); 2605 if (InputFile != NULL) { 2606 // each line represents a new fragment 2607 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - *buffer"); 2608 // 1. parse keysets and insert into temp. graph 2609 while (!InputFile.eof()) { 2610 InputFile.getline(buffer, MAXSTRINGSIZE); 2611 KeySet CurrentSet; 2612 if ((strlen(buffer) > 0) && (ScanBufferIntoKeySet(out, buffer, CurrentSet))) { // if at least one valid atom was added, write config 2613 testGraphInsert = FragmentList->insert(GraphPair (CurrentSet,pair<int,double>(NumberOfFragments++,1))); // store fragment number and current factor 2614 if (!testGraphInsert.second) { 2615 cerr << "KeySet file must be corrupt as there are two equal key sets therein!" << endl; 2616 } 2617 } 2618 } 2619 // 2. Free and done 2620 InputFile.close(); 2621 InputFile.clear(); 2622 Free((void **)&buffer, "molecule::ParseKeySetFile - *buffer"); 2623 *out << Verbose(1) << "done." << endl; 2624 } else { 2625 *out << Verbose(1) << "File " << filename << " not found." << endl; 2626 status = false; 2627 } 2628 2629 // 2nd pass: open TEFactors file and read 2630 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; 2631 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, TEFACTORSFILE); 2632 InputFile.open(filename); 2633 if (InputFile != NULL) { 2634 // 3. add found TEFactors to each keyset 2635 NumberOfFragments = 0; 2636 for(Graph::iterator runner = FragmentList->begin();runner != FragmentList->end(); runner++) { 2637 if (!InputFile.eof()) { 2638 InputFile >> TEFactor; 2639 (*runner).second.second = TEFactor; 2640 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2641 } else { 2642 status = false; 2643 break; 2644 } 2645 } 2646 // 4. Free and done 2647 InputFile.close(); 2648 *out << Verbose(1) << "done." << endl; 2649 } else { 2650 *out << Verbose(1) << "File " << filename << " not found." << endl; 2651 status = false; 2652 } 2653 2654 // free memory 2655 Free((void **)&filename, "molecule::ParseKeySetFile - filename"); 2656 2657 return status; 2658 2658 }; 2659 2659 … … 2666 2666 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 2667 2667 { 2668 ofstream output;2669 bool status =true;2670 string line;2671 2672 // open KeySet file2673 line = path;2674 line.append("/");2675 line += FRAGMENTPREFIX;2676 line += KEYSETFILE;2677 output.open(line.c_str(), ios::out);2678 *out << Verbose(1) << "Saving key sets of the total graph ... ";2679 if(output != NULL) {2680 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) {2681 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {2682 if (sprinter != (*runner).first.begin())2683 output << "\t";2684 output << *sprinter;2685 }2686 output << endl;2687 }2688 *out << "done." << endl;2689 } else {2690 cerr << "Unable to open " << line << " for writing keysets!" << endl;2691 status = false;2692 }2693 output.close();2694 output.clear();2695 2696 // open TEFactors file2697 line = path;2698 line.append("/");2699 line += FRAGMENTPREFIX;2700 line += TEFACTORSFILE;2701 output.open(line.c_str(), ios::out);2702 *out << Verbose(1) << "Saving TEFactors of the total graph ... ";2703 if(output != NULL) {2704 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++)2705 output << (*runner).second.second << endl;2706 *out << Verbose(1) << "done." << endl;2707 } else {2708 *out << Verbose(1) << "failed to open " << line << "." << endl;2709 status = false;2710 }2711 output.close();2712 2713 return status;2668 ofstream output; 2669 bool status = true; 2670 string line; 2671 2672 // open KeySet file 2673 line = path; 2674 line.append("/"); 2675 line += FRAGMENTPREFIX; 2676 line += KEYSETFILE; 2677 output.open(line.c_str(), ios::out); 2678 *out << Verbose(1) << "Saving key sets of the total graph ... "; 2679 if(output != NULL) { 2680 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2681 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2682 if (sprinter != (*runner).first.begin()) 2683 output << "\t"; 2684 output << *sprinter; 2685 } 2686 output << endl; 2687 } 2688 *out << "done." << endl; 2689 } else { 2690 cerr << "Unable to open " << line << " for writing keysets!" << endl; 2691 status = false; 2692 } 2693 output.close(); 2694 output.clear(); 2695 2696 // open TEFactors file 2697 line = path; 2698 line.append("/"); 2699 line += FRAGMENTPREFIX; 2700 line += TEFACTORSFILE; 2701 output.open(line.c_str(), ios::out); 2702 *out << Verbose(1) << "Saving TEFactors of the total graph ... "; 2703 if(output != NULL) { 2704 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) 2705 output << (*runner).second.second << endl; 2706 *out << Verbose(1) << "done." << endl; 2707 } else { 2708 *out << Verbose(1) << "failed to open " << line << "." << endl; 2709 status = false; 2710 } 2711 output.close(); 2712 2713 return status; 2714 2714 }; 2715 2715 … … 2722 2722 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 2723 2723 { 2724 ofstream AdjacencyFile;2725 atom *Walker = NULL;2726 stringstream line;2727 bool status = true;2728 2729 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2730 AdjacencyFile.open(line.str().c_str(), ios::out);2731 *out << Verbose(1) << "Saving adjacency list ... ";2732 if (AdjacencyFile != NULL) {2733 Walker = start;2734 while(Walker->next != end) {2735 Walker = Walker->next;2736 AdjacencyFile << Walker->nr << "\t";2737 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)2738 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t";2739 AdjacencyFile << endl;2740 }2741 AdjacencyFile.close();2742 *out << Verbose(1) << "done." << endl;2743 } else {2744 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;2745 status = false;2746 }2747 2748 return status;2724 ofstream AdjacencyFile; 2725 atom *Walker = NULL; 2726 stringstream line; 2727 bool status = true; 2728 2729 line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2730 AdjacencyFile.open(line.str().c_str(), ios::out); 2731 *out << Verbose(1) << "Saving adjacency list ... "; 2732 if (AdjacencyFile != NULL) { 2733 Walker = start; 2734 while(Walker->next != end) { 2735 Walker = Walker->next; 2736 AdjacencyFile << Walker->nr << "\t"; 2737 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) 2738 AdjacencyFile << ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker)->nr << "\t"; 2739 AdjacencyFile << endl; 2740 } 2741 AdjacencyFile.close(); 2742 *out << Verbose(1) << "done." << endl; 2743 } else { 2744 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 2745 status = false; 2746 } 2747 2748 return status; 2749 2749 }; 2750 2750 … … 2757 2757 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2758 2758 { 2759 ifstream File;2760 stringstream filename;2761 bool status = true;2762 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2763 2764 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;2765 File.open(filename.str().c_str(), ios::out);2766 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";2767 if (File != NULL) {2768 // allocate storage structure2769 int NonMatchNumber = 0;// will number of atoms with differing bond structure2770 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom2771 int CurrentBondsOfAtom;2772 2773 // Parse the file line by line and count the bonds2774 while (!File.eof()) {2775 File.getline(buffer, MAXSTRINGSIZE);2776 stringstream line;2777 line.str(buffer);2778 int AtomNr = -1;2779 line >> AtomNr;2780 CurrentBondsOfAtom = -1; // we count one too far due to line end2781 // parse into structure2782 if ((AtomNr >= 0) && (AtomNr < AtomCount)) {2783 while (!line.eof())2784 line >> CurrentBonds[ ++CurrentBondsOfAtom ];2785 // compare against present bonds2786 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: ";2787 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) {2788 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) {2789 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr;2790 int j = 0;2791 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds2792 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms2793 ListOfAtoms[AtomNr] = NULL;2794 NonMatchNumber++;2795 status = false;2796 //out << "[" << id << "]\t";2797 } else {2798 //out << id << "\t";2799 }2800 }2801 //out << endl;2802 } else {2803 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;2804 status = false;2805 }2806 }2807 }2808 File.close();2809 File.clear();2810 if (status) { // if equal we parse the KeySetFile2811 *out << Verbose(1) << "done: Equal." << endl;2812 status = true;2813 } else2814 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl;2815 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds");2816 } else {2817 *out << Verbose(1) << "Adjacency file not found." << endl;2818 status = false;2819 }2820 *out << endl;2821 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");2822 2823 return status;2759 ifstream File; 2760 stringstream filename; 2761 bool status = true; 2762 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2763 2764 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2765 File.open(filename.str().c_str(), ios::out); 2766 *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... "; 2767 if (File != NULL) { 2768 // allocate storage structure 2769 int NonMatchNumber = 0; // will number of atoms with differing bond structure 2770 int *CurrentBonds = (int *) Malloc(sizeof(int)*8, "molecule::CheckAdjacencyFileAgainstMolecule - CurrentBonds"); // contains parsed bonds of current atom 2771 int CurrentBondsOfAtom; 2772 2773 // Parse the file line by line and count the bonds 2774 while (!File.eof()) { 2775 File.getline(buffer, MAXSTRINGSIZE); 2776 stringstream line; 2777 line.str(buffer); 2778 int AtomNr = -1; 2779 line >> AtomNr; 2780 CurrentBondsOfAtom = -1; // we count one too far due to line end 2781 // parse into structure 2782 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2783 while (!line.eof()) 2784 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2785 // compare against present bonds 2786 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2787 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2788 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2789 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2790 int j = 0; 2791 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2792 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2793 ListOfAtoms[AtomNr] = NULL; 2794 NonMatchNumber++; 2795 status = false; 2796 //out << "[" << id << "]\t"; 2797 } else { 2798 //out << id << "\t"; 2799 } 2800 } 2801 //out << endl; 2802 } else { 2803 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2804 status = false; 2805 } 2806 } 2807 } 2808 File.close(); 2809 File.clear(); 2810 if (status) { // if equal we parse the KeySetFile 2811 *out << Verbose(1) << "done: Equal." << endl; 2812 status = true; 2813 } else 2814 *out << Verbose(1) << "done: Not equal by " << NonMatchNumber << " atoms." << endl; 2815 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2816 } else { 2817 *out << Verbose(1) << "Adjacency file not found." << endl; 2818 status = false; 2819 } 2820 *out << endl; 2821 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2822 2823 return status; 2824 2824 }; 2825 2825 … … 2835 2835 bool molecule::CheckOrderAtSite(ofstream *out, bool *AtomMask, Graph *GlobalKeySetList, int Order, int *MinimumRingSize, char *path) 2836 2836 { 2837 atom *Walker = start;2838 bool status = false;2839 ifstream InputFile;2840 2841 // initialize mask list2842 for(int i=AtomCount;i--;)2843 AtomMask[i] = false;2844 2845 if (Order < 0) { // adaptive increase of BondOrder per site2846 if (AtomMask[AtomCount] == true)// break after one step2847 return false;2848 // parse the EnergyPerFragment file2849 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer");2850 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT);2851 InputFile.open(buffer, ios::in);2852 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) {2853 // transmorph graph keyset list into indexed KeySetList2854 map<int,KeySet> IndexKeySetList;2855 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) {2856 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) );2857 }2858 int lines = 0;2859 // count the number of lines, i.e. the number of fragments2860 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2861 InputFile.getline(buffer, MAXSTRINGSIZE);2862 while(!InputFile.eof()) {2863 InputFile.getline(buffer, MAXSTRINGSIZE);2864 lines++;2865 }2866 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl;// one endline too much2867 InputFile.clear();2868 InputFile.seekg(ios::beg);2869 map<int, pair<double,int> > AdaptiveCriteriaList;// (Root No., (Value, Order)) !2870 int No, FragOrder;2871 double Value;2872 // each line represents a fragment root (Atom::nr) id and its energy contribution2873 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines2874 InputFile.getline(buffer, MAXSTRINGSIZE);2875 while(!InputFile.eof()) {2876 InputFile.getline(buffer, MAXSTRINGSIZE);2877 if (strlen(buffer) > 2) {2878 //*out << Verbose(2) << "Scanning: " << buffer << endl;2879 stringstream line(buffer);2880 line >> FragOrder;2881 line >> ws >> No;2882 line >> ws >> Value; // skip time entry2883 line >> ws >> Value;2884 No -= 1;// indices start at 1 in file, not 02885 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl;2886 2887 // clean the list of those entries that have been superceded by higher order terms already2888 map<int,KeySet>::iterator marker = IndexKeySetList.find(No);// find keyset to Frag No.2889 if (marker != IndexKeySetList.end()) {// if found2890 Value *= 1 + MYEPSILON*(*((*marker).second.begin()));// in case of equal energies this makes em not equal without changing anything actually2891 // 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 AtomMask2892 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) ));2893 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first;2894 if (!InsertedElement.second) { // this root is already present2895 if ((*PresentItem).second.second < FragOrder)// if order there is lower, update entry with higher-order term2896 //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)2897 {// if value is smaller, update value and order2898 (*PresentItem).second.first = fabs(Value);2899 (*PresentItem).second.second = FragOrder;2900 *out << Verbose(2) << "Updated element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2901 } else {2902 *out << Verbose(2) << "Did not update element " <<(*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl;2903 }2904 } else {2905 *out << Verbose(2) << "Inserted element (" <<(*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl;2906 }2907 } else {2908 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl;2909 }2910 }2911 }2912 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones)2913 map<double, pair<int,int> > FinalRootCandidates;2914 *out << Verbose(1) << "Root candidate list is: " << endl;2915 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) {2916 Walker = FindAtom((*runner).first);2917 if (Walker != NULL) {2918 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order2919 if (!Walker->MaxOrder) {2920 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl;2921 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) );2922 } else {2923 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl;2924 }2925 } else {2926 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl;2927 }2928 }2929 // pick the ones still below threshold and mark as to be adaptively updated2930 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) {2931 No = (*runner).second.first;2932 Walker = FindAtom(No);2933 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) {2934 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl;2935 AtomMask[No] = true;2936 status = true;2937 //} else2938 //*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;2939 }2940 // close and done2941 InputFile.close();2942 InputFile.clear();2943 } else {2944 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl;2945 while (Walker->next != end) {2946 Walker = Walker->next;2947 #ifdef ADDHYDROGEN2948 if (Walker->type->Z != 1) // skip hydrogen2949 #endif2950 {2951 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2952 status = true;2953 }2954 }2955 }2956 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer");2957 // pick a given number of highest values and set AtomMask2958 } else { // global increase of Bond Order2959 while (Walker->next != end) {2960 Walker = Walker->next;2961 #ifdef ADDHYDROGEN2962 if (Walker->type->Z != 1) // skip hydrogen2963 #endif2964 {2965 AtomMask[Walker->nr] = true;// include all (non-hydrogen) atoms2966 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]))2967 status = true;2968 }2969 }2970 if ((Order == 0) && (AtomMask[AtomCount] == false))// single stepping, just check2971 status = true;2972 2973 if (!status) {2974 if (Order == 0)2975 *out << Verbose(1) << "Single stepping done." << endl;2976 else2977 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl;2978 }2979 }2980 2981 // print atom mask for debugging2982 *out << "";2983 for(int i=0;i<AtomCount;i++)2984 *out << (i % 10);2985 *out << endl << "Atom mask is: ";2986 for(int i=0;i<AtomCount;i++)2987 *out << (AtomMask[i] ? "t" : "f");2988 *out << endl;2989 2990 return status;2837 atom *Walker = start; 2838 bool status = false; 2839 ifstream InputFile; 2840 2841 // initialize mask list 2842 for(int i=AtomCount;i--;) 2843 AtomMask[i] = false; 2844 2845 if (Order < 0) { // adaptive increase of BondOrder per site 2846 if (AtomMask[AtomCount] == true) // break after one step 2847 return false; 2848 // parse the EnergyPerFragment file 2849 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 2850 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 2851 InputFile.open(buffer, ios::in); 2852 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 2853 // transmorph graph keyset list into indexed KeySetList 2854 map<int,KeySet> IndexKeySetList; 2855 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 2856 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 2857 } 2858 int lines = 0; 2859 // count the number of lines, i.e. the number of fragments 2860 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2861 InputFile.getline(buffer, MAXSTRINGSIZE); 2862 while(!InputFile.eof()) { 2863 InputFile.getline(buffer, MAXSTRINGSIZE); 2864 lines++; 2865 } 2866 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 2867 InputFile.clear(); 2868 InputFile.seekg(ios::beg); 2869 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 2870 int No, FragOrder; 2871 double Value; 2872 // each line represents a fragment root (Atom::nr) id and its energy contribution 2873 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 2874 InputFile.getline(buffer, MAXSTRINGSIZE); 2875 while(!InputFile.eof()) { 2876 InputFile.getline(buffer, MAXSTRINGSIZE); 2877 if (strlen(buffer) > 2) { 2878 //*out << Verbose(2) << "Scanning: " << buffer << endl; 2879 stringstream line(buffer); 2880 line >> FragOrder; 2881 line >> ws >> No; 2882 line >> ws >> Value; // skip time entry 2883 line >> ws >> Value; 2884 No -= 1; // indices start at 1 in file, not 0 2885 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2886 2887 // clean the list of those entries that have been superceded by higher order terms already 2888 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 2889 if (marker != IndexKeySetList.end()) { // if found 2890 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 2891 // 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 2892 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2893 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2894 if (!InsertedElement.second) { // this root is already present 2895 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2896 //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) 2897 { // if value is smaller, update value and order 2898 (*PresentItem).second.first = fabs(Value); 2899 (*PresentItem).second.second = FragOrder; 2900 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2901 } else { 2902 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 2903 } 2904 } else { 2905 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 2906 } 2907 } else { 2908 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 2909 } 2910 } 2911 } 2912 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 2913 map<double, pair<int,int> > FinalRootCandidates; 2914 *out << Verbose(1) << "Root candidate list is: " << endl; 2915 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 2916 Walker = FindAtom((*runner).first); 2917 if (Walker != NULL) { 2918 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 2919 if (!Walker->MaxOrder) { 2920 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 2921 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 2922 } else { 2923 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 2924 } 2925 } else { 2926 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 2927 } 2928 } 2929 // pick the ones still below threshold and mark as to be adaptively updated 2930 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 2931 No = (*runner).second.first; 2932 Walker = FindAtom(No); 2933 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2934 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2935 AtomMask[No] = true; 2936 status = true; 2937 //} else 2938 //*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; 2939 } 2940 // close and done 2941 InputFile.close(); 2942 InputFile.clear(); 2943 } else { 2944 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 2945 while (Walker->next != end) { 2946 Walker = Walker->next; 2947 #ifdef ADDHYDROGEN 2948 if (Walker->type->Z != 1) // skip hydrogen 2949 #endif 2950 { 2951 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2952 status = true; 2953 } 2954 } 2955 } 2956 Free((void **)&buffer, "molecule::CheckOrderAtSite: *buffer"); 2957 // pick a given number of highest values and set AtomMask 2958 } else { // global increase of Bond Order 2959 while (Walker->next != end) { 2960 Walker = Walker->next; 2961 #ifdef ADDHYDROGEN 2962 if (Walker->type->Z != 1) // skip hydrogen 2963 #endif 2964 { 2965 AtomMask[Walker->nr] = true; // include all (non-hydrogen) atoms 2966 if ((Order != 0) && (Walker->AdaptiveOrder < Order)) // && (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr])) 2967 status = true; 2968 } 2969 } 2970 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2971 status = true; 2972 2973 if (!status) { 2974 if (Order == 0) 2975 *out << Verbose(1) << "Single stepping done." << endl; 2976 else 2977 *out << Verbose(1) << "Order at every site is already equal or above desired order " << Order << "." << endl; 2978 } 2979 } 2980 2981 // print atom mask for debugging 2982 *out << " "; 2983 for(int i=0;i<AtomCount;i++) 2984 *out << (i % 10); 2985 *out << endl << "Atom mask is: "; 2986 for(int i=0;i<AtomCount;i++) 2987 *out << (AtomMask[i] ? "t" : "f"); 2988 *out << endl; 2989 2990 return status; 2991 2991 }; 2992 2992 … … 2998 2998 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 2999 2999 { 3000 element *runner = elemente->start;3001 int AtomNo = 0;3002 atom *Walker = NULL;3003 3004 if (SortIndex != NULL) {3005 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;3006 return false;3007 }3008 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex");3009 for(int i=AtomCount;i--;)3010 SortIndex[i] = -1;3011 while (runner->next != elemente->end) { // go through every element3012 runner = runner->next;3013 if (ElementsInMolecule[runner->Z]) { // if this element got atoms3014 Walker = start;3015 while (Walker->next != end) { // go through every atom of this element3016 Walker = Walker->next;3017 if (Walker->type->Z == runner->Z) // if this atom fits to element3018 SortIndex[Walker->nr] = AtomNo++;3019 }3020 }3021 }3022 return true;3000 element *runner = elemente->start; 3001 int AtomNo = 0; 3002 atom *Walker = NULL; 3003 3004 if (SortIndex != NULL) { 3005 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 3006 return false; 3007 } 3008 SortIndex = (int *) Malloc(sizeof(int)*AtomCount, "molecule::FragmentMolecule: *SortIndex"); 3009 for(int i=AtomCount;i--;) 3010 SortIndex[i] = -1; 3011 while (runner->next != elemente->end) { // go through every element 3012 runner = runner->next; 3013 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 3014 Walker = start; 3015 while (Walker->next != end) { // go through every atom of this element 3016 Walker = Walker->next; 3017 if (Walker->type->Z == runner->Z) // if this atom fits to element 3018 SortIndex[Walker->nr] = AtomNo++; 3019 } 3020 } 3021 } 3022 return true; 3023 3023 }; 3024 3024 … … 3029 3029 y contribution", and that's why this consciously not done in the following loop) 3030 3030 * -# in a loop over all subgraphs 3031 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure3032 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet)3031 * -# calls FragmentBOSSANOVA with this RootStack and within the subgraph molecule structure 3032 * -# creates molecule (fragment)s from the returned keysets (StoreFragmentFromKeySet) 3033 3033 * -# combines the generated molecule lists from all subgraphs 3034 3034 * -# saves to disk: fragment configs, adjacency, orderatsite, keyset files … … 3043 3043 int molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 3044 3044 { 3045 MoleculeListClass *BondFragments = NULL;3046 int *SortIndex = NULL;3047 int *MinimumRingSize = new int[AtomCount];3048 int FragmentCounter;3049 MoleculeLeafClass *MolecularWalker = NULL;3050 MoleculeLeafClass *Subgraphs = NULL;// list of subgraphs from DFS analysis3051 fstream File;3052 bool FragmentationToDo = true;3053 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL;3054 bool CheckOrder = false;3055 Graph **FragmentList = NULL;3056 Graph *ParsedFragmentList = NULL;3057 Graph TotalGraph;// graph with all keysets however local numbers3058 int TotalNumberOfKeySets = 0;3059 atom **ListOfAtoms = NULL;3060 atom ***ListOfLocalAtoms = NULL;3061 bool *AtomMask = NULL;3062 3063 *out << endl;3045 MoleculeListClass *BondFragments = NULL; 3046 int *SortIndex = NULL; 3047 int *MinimumRingSize = new int[AtomCount]; 3048 int FragmentCounter; 3049 MoleculeLeafClass *MolecularWalker = NULL; 3050 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 3051 fstream File; 3052 bool FragmentationToDo = true; 3053 class StackClass<bond *> *BackEdgeStack = NULL, *LocalBackEdgeStack = NULL; 3054 bool CheckOrder = false; 3055 Graph **FragmentList = NULL; 3056 Graph *ParsedFragmentList = NULL; 3057 Graph TotalGraph; // graph with all keysets however local numbers 3058 int TotalNumberOfKeySets = 0; 3059 atom **ListOfAtoms = NULL; 3060 atom ***ListOfLocalAtoms = NULL; 3061 bool *AtomMask = NULL; 3062 3063 *out << endl; 3064 3064 #ifdef ADDHYDROGEN 3065 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;3065 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 3066 3066 #else 3067 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;3067 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 3068 3068 #endif 3069 3069 3070 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++3071 3072 // ===== 1. Check whether bond structure is same as stored in files ====3073 3074 // fill the adjacency list3075 CreateListOfBondsPerAtom(out);3076 3077 // create lookup table for Atom::nr3078 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount);3079 3080 // === compare it with adjacency file ===3081 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms);3082 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms");3083 3084 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====3085 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack);3086 // fill the bond structure of the individually stored subgraphs3087 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);// we want to keep the created ListOfLocalAtoms3088 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph3089 for(int i=AtomCount;i--;)3090 MinimumRingSize[i] = AtomCount;3091 MolecularWalker = Subgraphs;3092 FragmentCounter = 0;3093 while (MolecularWalker->next != NULL) {3094 MolecularWalker = MolecularWalker->next;3095 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount);3096 // // check the list of local atoms for debugging3097 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl;3098 // for (int i=0;i<AtomCount;i++)3099 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL)3100 // *out << "\tNULL";3101 // else3102 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name;3103 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3104 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack);3105 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3106 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize);3107 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl;3108 delete(LocalBackEdgeStack);3109 }3110 3111 // ===== 3. if structure still valid, parse key set file and others =====3112 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);3113 3114 // ===== 4. check globally whether there's something to do actually (first adaptivity check)3115 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath);3116 3117 // =================================== Begin of FRAGMENTATION ===============================3118 // ===== 6a. assign each keyset to its respective subgraph =====3119 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true);3120 3121 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle3122 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];3123 AtomMask = new bool[AtomCount+1];3124 AtomMask[AtomCount] = false;3125 FragmentationToDo = false;// if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards3126 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) {3127 FragmentationToDo = FragmentationToDo || CheckOrder;3128 AtomMask[AtomCount] = true;// last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()3129 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====3130 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0));3131 3132 // ===== 7. fill the bond fragment list =====3133 FragmentCounter = 0;3134 MolecularWalker = Subgraphs;3135 while (MolecularWalker->next != NULL) {3136 MolecularWalker = MolecularWalker->next;3137 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;3138 //MolecularWalker->Leaf->OutputListOfBonds(out);// output ListOfBondsPerAtom for debugging3139 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) {3140 // call BOSSANOVA method3141 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl;3142 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize);3143 } else {3144 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl;3145 }3146 FragmentCounter++;// next fragment list3147 }3148 }3149 delete[](RootStack);3150 delete[](AtomMask);3151 delete(ParsedFragmentList);3152 delete[](MinimumRingSize);3153 3154 3155 // ==================================== End of FRAGMENTATION ============================================3156 3157 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)3158 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);3159 3160 // free subgraph memory again3161 FragmentCounter = 0;3162 if (Subgraphs != NULL) {3163 while (Subgraphs->next != NULL) {3164 Subgraphs = Subgraphs->next;3165 delete(FragmentList[FragmentCounter++]);3166 delete(Subgraphs->previous);3167 }3168 delete(Subgraphs);3169 }3170 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList");3171 3172 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====3173 //if (FragmentationToDo) {// we should always store the fragments again as coordination might have changed slightly without changing bond structure3174 // allocate memory for the pointer array and transmorph graphs into full molecular fragments3175 BondFragments = new MoleculeListClass();3176 int k=0;3177 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {3178 KeySet test = (*runner).first;3179 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl;3180 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration));3181 k++;3182 }3183 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl;3184 3185 // ===== 9. Save fragments' configuration and keyset files et al to disk ===3186 if (BondFragments->ListOfMolecules.size() != 0) {3187 // create the SortIndex from BFS labels to order in the config file3188 CreateMappingLabelsToConfigSequence(out, SortIndex);3189 3190 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl;3191 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex))3192 *out << Verbose(1) << "All configs written." << endl;3193 else3194 *out << Verbose(1) << "Some config writing failed." << endl;3195 3196 // store force index reference file3197 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex);3198 3199 // store keysets file3200 StoreKeySetFile(out, TotalGraph, configuration->configpath);3201 3202 // store Adjacency file3203 StoreAdjacencyToFile(out, configuration->configpath);3204 3205 // store Hydrogen saturation correction file3206 BondFragments->AddHydrogenCorrection(out, configuration->configpath);3207 3208 // store adaptive orders into file3209 StoreOrderAtSiteFile(out, configuration->configpath);3210 3211 // restore orbital and Stop values3212 CalculateOrbitals(*configuration);3213 3214 // free memory for bond part3215 *out << Verbose(1) << "Freeing bond memory" << endl;3216 delete(FragmentList); // remove bond molecule from memory3217 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex");3218 } else3219 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl;3220 //} else3221 //*out << Verbose(1) << "No fragments to store." << endl;3222 *out << Verbose(0) << "End of bond fragmentation." << endl;3223 3224 return ((int)(!FragmentationToDo)+1);// 1 - continue, 2 - stop (no fragmentation occured)3070 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 3071 3072 // ===== 1. Check whether bond structure is same as stored in files ==== 3073 3074 // fill the adjacency list 3075 CreateListOfBondsPerAtom(out); 3076 3077 // create lookup table for Atom::nr 3078 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 3079 3080 // === compare it with adjacency file === 3081 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 3082 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 3083 3084 // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs ===== 3085 Subgraphs = DepthFirstSearchAnalysis(out, BackEdgeStack); 3086 // fill the bond structure of the individually stored subgraphs 3087 Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false); // we want to keep the created ListOfLocalAtoms 3088 // analysis of the cycles (print rings, get minimum cycle length) for each subgraph 3089 for(int i=AtomCount;i--;) 3090 MinimumRingSize[i] = AtomCount; 3091 MolecularWalker = Subgraphs; 3092 FragmentCounter = 0; 3093 while (MolecularWalker->next != NULL) { 3094 MolecularWalker = MolecularWalker->next; 3095 LocalBackEdgeStack = new StackClass<bond *> (MolecularWalker->Leaf->BondCount); 3096 // // check the list of local atoms for debugging 3097 // *out << Verbose(0) << "ListOfLocalAtoms for this subgraph is:" << endl; 3098 // for (int i=0;i<AtomCount;i++) 3099 // if (ListOfLocalAtoms[FragmentCounter][i] == NULL) 3100 // *out << "\tNULL"; 3101 // else 3102 // *out << "\t" << ListOfLocalAtoms[FragmentCounter][i]->Name; 3103 *out << Verbose(0) << "Gathering local back edges for subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3104 MolecularWalker->Leaf->PickLocalBackEdges(out, ListOfLocalAtoms[FragmentCounter++], BackEdgeStack, LocalBackEdgeStack); 3105 *out << Verbose(0) << "Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3106 MolecularWalker->Leaf->CyclicStructureAnalysis(out, LocalBackEdgeStack, MinimumRingSize); 3107 *out << Verbose(0) << "Done with Analysing the cycles of subgraph " << MolecularWalker->Leaf << " with nr. " << FragmentCounter << "." << endl; 3108 delete(LocalBackEdgeStack); 3109 } 3110 3111 // ===== 3. if structure still valid, parse key set file and others ===== 3112 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); 3113 3114 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 3115 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 3116 3117 // =================================== Begin of FRAGMENTATION =============================== 3118 // ===== 6a. assign each keyset to its respective subgraph ===== 3119 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 3120 3121 // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle 3122 KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()]; 3123 AtomMask = new bool[AtomCount+1]; 3124 AtomMask[AtomCount] = false; 3125 FragmentationToDo = false; // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards 3126 while ((CheckOrder = CheckOrderAtSite(out, AtomMask, ParsedFragmentList, Order, MinimumRingSize, configuration->configpath))) { 3127 FragmentationToDo = FragmentationToDo || CheckOrder; 3128 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 3129 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3130 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 3131 3132 // ===== 7. fill the bond fragment list ===== 3133 FragmentCounter = 0; 3134 MolecularWalker = Subgraphs; 3135 while (MolecularWalker->next != NULL) { 3136 MolecularWalker = MolecularWalker->next; 3137 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 3138 //MolecularWalker->Leaf->OutputListOfBonds(out); // output ListOfBondsPerAtom for debugging 3139 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 3140 // call BOSSANOVA method 3141 *out << Verbose(0) << endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= " << endl; 3142 MolecularWalker->Leaf->FragmentBOSSANOVA(out, FragmentList[FragmentCounter], RootStack[FragmentCounter], MinimumRingSize); 3143 } else { 3144 cerr << "Subgraph " << MolecularWalker << " has no atoms!" << endl; 3145 } 3146 FragmentCounter++; // next fragment list 3147 } 3148 } 3149 delete[](RootStack); 3150 delete[](AtomMask); 3151 delete(ParsedFragmentList); 3152 delete[](MinimumRingSize); 3153 3154 3155 // ==================================== End of FRAGMENTATION ============================================ 3156 3157 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3158 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3159 3160 // free subgraph memory again 3161 FragmentCounter = 0; 3162 if (Subgraphs != NULL) { 3163 while (Subgraphs->next != NULL) { 3164 Subgraphs = Subgraphs->next; 3165 delete(FragmentList[FragmentCounter++]); 3166 delete(Subgraphs->previous); 3167 } 3168 delete(Subgraphs); 3169 } 3170 Free((void **)&FragmentList, "molecule::FragmentMolecule - **FragmentList"); 3171 3172 // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass ===== 3173 //if (FragmentationToDo) { // we should always store the fragments again as coordination might have changed slightly without changing bond structure 3174 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 3175 BondFragments = new MoleculeListClass(); 3176 int k=0; 3177 for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) { 3178 KeySet test = (*runner).first; 3179 *out << "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << "." << endl; 3180 BondFragments->insert(StoreFragmentFromKeySet(out, test, configuration)); 3181 k++; 3182 } 3183 *out << k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets." << endl; 3184 3185 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3186 if (BondFragments->ListOfMolecules.size() != 0) { 3187 // create the SortIndex from BFS labels to order in the config file 3188 CreateMappingLabelsToConfigSequence(out, SortIndex); 3189 3190 *out << Verbose(1) << "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs" << endl; 3191 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) 3192 *out << Verbose(1) << "All configs written." << endl; 3193 else 3194 *out << Verbose(1) << "Some config writing failed." << endl; 3195 3196 // store force index reference file 3197 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3198 3199 // store keysets file 3200 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3201 3202 // store Adjacency file 3203 StoreAdjacencyToFile(out, configuration->configpath); 3204 3205 // store Hydrogen saturation correction file 3206 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3207 3208 // store adaptive orders into file 3209 StoreOrderAtSiteFile(out, configuration->configpath); 3210 3211 // restore orbital and Stop values 3212 CalculateOrbitals(*configuration); 3213 3214 // free memory for bond part 3215 *out << Verbose(1) << "Freeing bond memory" << endl; 3216 delete(FragmentList); // remove bond molecule from memory 3217 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3218 } else 3219 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3220 //} else 3221 // *out << Verbose(1) << "No fragments to store." << endl; 3222 *out << Verbose(0) << "End of bond fragmentation." << endl; 3223 3224 return ((int)(!FragmentationToDo)+1); // 1 - continue, 2 - stop (no fragmentation occured) 3225 3225 }; 3226 3226 … … 3235 3235 bool molecule::PickLocalBackEdges(ofstream *out, atom **ListOfLocalAtoms, class StackClass<bond *> *&ReferenceStack, class StackClass<bond *> *&LocalStack) 3236 3236 { 3237 bool status = true;3238 if (ReferenceStack->IsEmpty()) {3239 cerr << "ReferenceStack is empty!" << endl;3240 return false;3241 }3242 bond *Binder = ReferenceStack->PopFirst();3243 bond *FirstBond = Binder;// mark the first bond, so that we don't loop through the stack indefinitely3244 atom *Walker = NULL, *OtherAtom = NULL;3245 ReferenceStack->Push(Binder);3246 3247 do {// go through all bonds and push local ones3248 Walker = ListOfLocalAtoms[Binder->leftatom->nr];// get one atom in the reference molecule3249 if (Walker != NULL) // if this Walker exists in the subgraph ...3250 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through the local list of bonds3251 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3252 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond3253 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]);3254 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl;3255 break;3256 }3257 }3258 Binder = ReferenceStack->PopFirst();// loop the stack for next item3259 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl;3260 ReferenceStack->Push(Binder);3261 } while (FirstBond != Binder);3262 3263 return status;3237 bool status = true; 3238 if (ReferenceStack->IsEmpty()) { 3239 cerr << "ReferenceStack is empty!" << endl; 3240 return false; 3241 } 3242 bond *Binder = ReferenceStack->PopFirst(); 3243 bond *FirstBond = Binder; // mark the first bond, so that we don't loop through the stack indefinitely 3244 atom *Walker = NULL, *OtherAtom = NULL; 3245 ReferenceStack->Push(Binder); 3246 3247 do { // go through all bonds and push local ones 3248 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3249 if (Walker != NULL) // if this Walker exists in the subgraph ... 3250 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3251 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3252 if (OtherAtom == ListOfLocalAtoms[Binder->rightatom->nr]) { // found the bond 3253 LocalStack->Push(ListOfBondsPerAtom[Walker->nr][i]); 3254 *out << Verbose(3) << "Found local edge " << *(ListOfBondsPerAtom[Walker->nr][i]) << "." << endl; 3255 break; 3256 } 3257 } 3258 Binder = ReferenceStack->PopFirst(); // loop the stack for next item 3259 *out << Verbose(3) << "Current candidate edge " << Binder << "." << endl; 3260 ReferenceStack->Push(Binder); 3261 } while (FirstBond != Binder); 3262 3263 return status; 3264 3264 }; 3265 3265 … … 3272 3272 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 3273 3273 { 3274 stringstream line;3275 ofstream file;3276 3277 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3278 file.open(line.str().c_str());3279 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;3280 if (file != NULL) {3281 atom *Walker = start;3282 while (Walker->next != end) {3283 Walker = Walker->next;3284 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl;3285 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl;3286 }3287 file.close();3288 *out << Verbose(1) << "done." << endl;3289 return true;3290 } else {3291 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3292 return false;3293 }3274 stringstream line; 3275 ofstream file; 3276 3277 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3278 file.open(line.str().c_str()); 3279 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 3280 if (file != NULL) { 3281 atom *Walker = start; 3282 while (Walker->next != end) { 3283 Walker = Walker->next; 3284 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 3285 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 3286 } 3287 file.close(); 3288 *out << Verbose(1) << "done." << endl; 3289 return true; 3290 } else { 3291 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3292 return false; 3293 } 3294 3294 }; 3295 3295 … … 3303 3303 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 3304 3304 { 3305 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3306 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3307 bool status;3308 int AtomNr, value;3309 stringstream line;3310 ifstream file;3311 3312 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl;3313 for(int i=AtomCount;i--;)3314 OrderArray[i] = 0;3315 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE;3316 file.open(line.str().c_str());3317 if (file != NULL) {3318 for (int i=AtomCount;i--;) { // initialise with 03319 OrderArray[i] = 0;3320 MaxArray[i] = 0;3321 }3322 while (!file.eof()) { // parse from file3323 AtomNr = -1;3324 file >> AtomNr;3325 if (AtomNr != -1) {// test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time)3326 file >> value;3327 OrderArray[AtomNr] = value;3328 file >> value;3329 MaxArray[AtomNr] = value;3330 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl;3331 }3332 }3333 atom *Walker = start;3334 while (Walker->next != end) { // fill into atom classes3335 Walker = Walker->next;3336 Walker->AdaptiveOrder = OrderArray[Walker->nr];3337 Walker->MaxOrder = MaxArray[Walker->nr];3338 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;3339 }3340 file.close();3341 *out << Verbose(1) << "done." << endl;3342 status = true;3343 } else {3344 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl;3345 status = false;3346 }3347 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray");3348 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray");3349 3350 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl;3351 return status;3305 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3306 bool *MaxArray = (bool *) Malloc(sizeof(bool)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3307 bool status; 3308 int AtomNr, value; 3309 stringstream line; 3310 ifstream file; 3311 3312 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 3313 for(int i=AtomCount;i--;) 3314 OrderArray[i] = 0; 3315 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 3316 file.open(line.str().c_str()); 3317 if (file != NULL) { 3318 for (int i=AtomCount;i--;) { // initialise with 0 3319 OrderArray[i] = 0; 3320 MaxArray[i] = 0; 3321 } 3322 while (!file.eof()) { // parse from file 3323 AtomNr = -1; 3324 file >> AtomNr; 3325 if (AtomNr != -1) { // test whether we really parsed something (this is necessary, otherwise last atom is set twice and to 0 on second time) 3326 file >> value; 3327 OrderArray[AtomNr] = value; 3328 file >> value; 3329 MaxArray[AtomNr] = value; 3330 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << "." << endl; 3331 } 3332 } 3333 atom *Walker = start; 3334 while (Walker->next != end) { // fill into atom classes 3335 Walker = Walker->next; 3336 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3337 Walker->MaxOrder = MaxArray[Walker->nr]; 3338 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3339 } 3340 file.close(); 3341 *out << Verbose(1) << "done." << endl; 3342 status = true; 3343 } else { 3344 *out << Verbose(1) << "failed to open file " << line.str() << "." << endl; 3345 status = false; 3346 } 3347 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3348 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3349 3350 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3351 return status; 3352 3352 }; 3353 3353 … … 3360 3360 void molecule::CreateListOfBondsPerAtom(ofstream *out) 3361 3361 { 3362 bond *Binder = NULL;3363 atom *Walker = NULL;3364 int TotalDegree;3365 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl;3366 3367 // re-allocate memory3368 *out << Verbose(2) << "(Re-)Allocating memory." << endl;3369 if (ListOfBondsPerAtom != NULL) {3370 for(int i=AtomCount;i--;)3371 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]");3372 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom");3373 }3374 if (NumberOfBondsPerAtom != NULL)3375 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom");3376 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom");3377 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom");3378 3379 // reset bond counts per atom3380 for(int i=AtomCount;i--;)3381 NumberOfBondsPerAtom[i] = 0;3382 // count bonds per atom3383 Binder = first;3384 while (Binder->next != last) {3385 Binder = Binder->next;3386 NumberOfBondsPerAtom[Binder->leftatom->nr]++;3387 NumberOfBondsPerAtom[Binder->rightatom->nr]++;3388 }3389 for(int i=AtomCount;i--;) {3390 // allocate list of bonds per atom3391 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]");3392 // clear the list again, now each NumberOfBondsPerAtom marks current free field3393 NumberOfBondsPerAtom[i] = 0;3394 }3395 // fill the list3396 Binder = first;3397 while (Binder->next != last) {3398 Binder = Binder->next;3399 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder;3400 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder;3401 }3402 3403 // output list for debugging3404 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl;3405 Walker = start;3406 while (Walker->next != end) {3407 Walker = Walker->next;3408 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: ";3409 TotalDegree = 0;3410 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) {3411 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t";3412 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;3413 }3414 *out << " -- TotalDegree: " << TotalDegree << endl;3415 }3416 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl;3362 bond *Binder = NULL; 3363 atom *Walker = NULL; 3364 int TotalDegree; 3365 *out << Verbose(1) << "Begin of Creating ListOfBondsPerAtom: AtomCount = " << AtomCount << "\tBondCount = " << BondCount << "\tNoNonBonds = " << NoNonBonds << "." << endl; 3366 3367 // re-allocate memory 3368 *out << Verbose(2) << "(Re-)Allocating memory." << endl; 3369 if (ListOfBondsPerAtom != NULL) { 3370 for(int i=AtomCount;i--;) 3371 Free((void **)&ListOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom[i]"); 3372 Free((void **)&ListOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: ListOfBondsPerAtom"); 3373 } 3374 if (NumberOfBondsPerAtom != NULL) 3375 Free((void **)&NumberOfBondsPerAtom, "molecule::CreateListOfBondsPerAtom: NumberOfBondsPerAtom"); 3376 ListOfBondsPerAtom = (bond ***) Malloc(sizeof(bond **)*AtomCount, "molecule::CreateListOfBondsPerAtom: ***ListOfBondsPerAtom"); 3377 NumberOfBondsPerAtom = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CreateListOfBondsPerAtom: *NumberOfBondsPerAtom"); 3378 3379 // reset bond counts per atom 3380 for(int i=AtomCount;i--;) 3381 NumberOfBondsPerAtom[i] = 0; 3382 // count bonds per atom 3383 Binder = first; 3384 while (Binder->next != last) { 3385 Binder = Binder->next; 3386 NumberOfBondsPerAtom[Binder->leftatom->nr]++; 3387 NumberOfBondsPerAtom[Binder->rightatom->nr]++; 3388 } 3389 for(int i=AtomCount;i--;) { 3390 // allocate list of bonds per atom 3391 ListOfBondsPerAtom[i] = (bond **) Malloc(sizeof(bond *)*NumberOfBondsPerAtom[i], "molecule::CreateListOfBondsPerAtom: **ListOfBondsPerAtom[]"); 3392 // clear the list again, now each NumberOfBondsPerAtom marks current free field 3393 NumberOfBondsPerAtom[i] = 0; 3394 } 3395 // fill the list 3396 Binder = first; 3397 while (Binder->next != last) { 3398 Binder = Binder->next; 3399 ListOfBondsPerAtom[Binder->leftatom->nr][NumberOfBondsPerAtom[Binder->leftatom->nr]++] = Binder; 3400 ListOfBondsPerAtom[Binder->rightatom->nr][NumberOfBondsPerAtom[Binder->rightatom->nr]++] = Binder; 3401 } 3402 3403 // output list for debugging 3404 *out << Verbose(3) << "ListOfBondsPerAtom for each atom:" << endl; 3405 Walker = start; 3406 while (Walker->next != end) { 3407 Walker = Walker->next; 3408 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3409 TotalDegree = 0; 3410 for (int j=0;j<NumberOfBondsPerAtom[Walker->nr];j++) { 3411 *out << *ListOfBondsPerAtom[Walker->nr][j] << "\t"; 3412 TotalDegree += ListOfBondsPerAtom[Walker->nr][j]->BondDegree; 3413 } 3414 *out << " -- TotalDegree: " << TotalDegree << endl; 3415 } 3416 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3417 3417 }; 3418 3418 … … 3431 3431 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3432 3432 { 3433 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList");3434 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList");3435 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList");3436 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);3437 atom *Walker = NULL, *OtherAtom = NULL;3438 bond *Binder = NULL;3439 3440 // add Root if not done yet3441 AtomStack->ClearStack();3442 if (AddedAtomList[Root->nr] == NULL)// add Root if not yet present3443 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root);3444 AtomStack->Push(Root);3445 3446 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray3447 for (int i=AtomCount;i--;) {3448 PredecessorList[i] = NULL;3449 ShortestPathList[i] = -1;3450 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited3451 ColorList[i] = lightgray;3452 else3453 ColorList[i] = white;3454 }3455 ShortestPathList[Root->nr] = 0;3456 3457 // and go on ... Queue always contains all lightgray vertices3458 while (!AtomStack->IsEmpty()) {3459 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance.3460 // 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 again3461 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and3462 // followed by n+1 till top of stack.3463 Walker = AtomStack->PopFirst(); // pop oldest added3464 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl;3465 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {3466 Binder = ListOfBondsPerAtom[Walker->nr][i];3467 if (Binder != NULL) { // don't look at bond equal NULL3468 OtherAtom = Binder->GetOtherAtom(Walker);3469 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;3470 if (ColorList[OtherAtom->nr] == white) {3471 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)3472 ColorList[OtherAtom->nr] = lightgray;3473 PredecessorList[OtherAtom->nr] = Walker;// Walker is the predecessor3474 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;3475 *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;3476 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance3477 *out << Verbose(3);3478 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far3479 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom);3480 *out << "Added OtherAtom " << OtherAtom->Name;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 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", ";3485 } 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)3486 *out << "Not adding OtherAtom " << OtherAtom->Name;3487 if (AddedBondList[Binder->nr] == NULL) {3488 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3489 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3490 AddedBondList[Binder->nr]->Type = Binder->Type;3491 *out << ", added Bond " << *(AddedBondList[Binder->nr]);3492 } else3493 *out << ", not added Bond ";3494 }3495 *out << ", putting OtherAtom into queue." << endl;3496 AtomStack->Push(OtherAtom);3497 } else { // out of bond order, then replace3498 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic))3499 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic)3500 if (Binder == Bond)3501 *out << Verbose(3) << "Not Queueing, is the Root bond";3502 else if (ShortestPathList[OtherAtom->nr] >= BondOrder)3503 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder;3504 if (!Binder->Cyclic)3505 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl;3506 if (AddedBondList[Binder->nr] == NULL) {3507 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate3508 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3509 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3510 AddedBondList[Binder->nr]->Type = Binder->Type;3511 } else {3433 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3434 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::BreadthFirstSearchAdd: *ShortestPathList"); 3435 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::BreadthFirstSearchAdd: *ColorList"); 3436 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 3437 atom *Walker = NULL, *OtherAtom = NULL; 3438 bond *Binder = NULL; 3439 3440 // add Root if not done yet 3441 AtomStack->ClearStack(); 3442 if (AddedAtomList[Root->nr] == NULL) // add Root if not yet present 3443 AddedAtomList[Root->nr] = Mol->AddCopyAtom(Root); 3444 AtomStack->Push(Root); 3445 3446 // initialise each vertex as white with no predecessor, empty queue, color Root lightgray 3447 for (int i=AtomCount;i--;) { 3448 PredecessorList[i] = NULL; 3449 ShortestPathList[i] = -1; 3450 if (AddedAtomList[i] != NULL) // mark already present atoms (i.e. Root and maybe others) as visited 3451 ColorList[i] = lightgray; 3452 else 3453 ColorList[i] = white; 3454 } 3455 ShortestPathList[Root->nr] = 0; 3456 3457 // and go on ... Queue always contains all lightgray vertices 3458 while (!AtomStack->IsEmpty()) { 3459 // we have to pop the oldest atom from stack. This keeps the atoms on the stack always of the same ShortestPath distance. 3460 // 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 3461 // append length of 3 (their neighbours). Thus on stack we have always atoms of a certain length n at bottom of stack and 3462 // followed by n+1 till top of stack. 3463 Walker = AtomStack->PopFirst(); // pop oldest added 3464 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3465 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3466 Binder = ListOfBondsPerAtom[Walker->nr][i]; 3467 if (Binder != NULL) { // don't look at bond equal NULL 3468 OtherAtom = Binder->GetOtherAtom(Walker); 3469 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3470 if (ColorList[OtherAtom->nr] == white) { 3471 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) 3472 ColorList[OtherAtom->nr] = lightgray; 3473 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3474 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3475 *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; 3476 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3477 *out << Verbose(3); 3478 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far 3479 AddedAtomList[OtherAtom->nr] = Mol->AddCopyAtom(OtherAtom); 3480 *out << "Added OtherAtom " << OtherAtom->Name; 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 *out << " and bond " << *(AddedBondList[Binder->nr]) << ", "; 3485 } 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) 3486 *out << "Not adding OtherAtom " << OtherAtom->Name; 3487 if (AddedBondList[Binder->nr] == NULL) { 3488 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3489 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3490 AddedBondList[Binder->nr]->Type = Binder->Type; 3491 *out << ", added Bond " << *(AddedBondList[Binder->nr]); 3492 } else 3493 *out << ", not added Bond "; 3494 } 3495 *out << ", putting OtherAtom into queue." << endl; 3496 AtomStack->Push(OtherAtom); 3497 } else { // out of bond order, then replace 3498 if ((AddedAtomList[OtherAtom->nr] == NULL) && (Binder->Cyclic)) 3499 ColorList[OtherAtom->nr] = white; // unmark if it has not been queued/added, to make it available via its other bonds (cyclic) 3500 if (Binder == Bond) 3501 *out << Verbose(3) << "Not Queueing, is the Root bond"; 3502 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 3503 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 3504 if (!Binder->Cyclic) 3505 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 3506 if (AddedBondList[Binder->nr] == NULL) { 3507 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 3508 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3509 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3510 AddedBondList[Binder->nr]->Type = Binder->Type; 3511 } else { 3512 3512 #ifdef ADDHYDROGEN 3513 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3514 exit(1);3513 if (!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3514 exit(1); 3515 3515 #endif 3516 }3517 }3518 }3519 } else {3520 *out << Verbose(3) << "Not Adding, has already been visited." << endl;3521 // This has to be a cyclic bond, check whether it's present ...3522 if (AddedBondList[Binder->nr] == NULL) {3523 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) {3524 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree);3525 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic;3526 AddedBondList[Binder->nr]->Type = Binder->Type;3527 } else { // if it's root bond it has to broken (otherwise we would not create the fragments)3516 } 3517 } 3518 } 3519 } else { 3520 *out << Verbose(3) << "Not Adding, has already been visited." << endl; 3521 // This has to be a cyclic bond, check whether it's present ... 3522 if (AddedBondList[Binder->nr] == NULL) { 3523 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3524 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3525 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; 3526 AddedBondList[Binder->nr]->Type = Binder->Type; 3527 } else { // if it's root bond it has to broken (otherwise we would not create the fragments) 3528 3528 #ifdef ADDHYDROGEN 3529 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem))3530 exit(1);3529 if(!Mol->AddHydrogenReplacementAtom(out, Binder, AddedAtomList[Walker->nr], Walker, OtherAtom, ListOfBondsPerAtom[Walker->nr], NumberOfBondsPerAtom[Walker->nr], IsAngstroem)) 3530 exit(1); 3531 3531 #endif 3532 }3533 }3534 }3535 }3536 }3537 ColorList[Walker->nr] = black;3538 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;3539 }3540 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList");3541 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList");3542 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList");3543 delete(AtomStack);3532 } 3533 } 3534 } 3535 } 3536 } 3537 ColorList[Walker->nr] = black; 3538 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3539 } 3540 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); 3541 Free((void **)&ShortestPathList, "molecule::BreadthFirstSearchAdd: **ShortestPathList"); 3542 Free((void **)&ColorList, "molecule::BreadthFirstSearchAdd: **ColorList"); 3543 delete(AtomStack); 3544 3544 }; 3545 3545 … … 3555 3555 bool molecule::BuildInducedSubgraph(ofstream *out, const molecule *Father) 3556 3556 { 3557 atom *Walker = NULL, *OtherAtom = NULL;3558 bool status = true;3559 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList");3560 3561 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl;3562 3563 // reset parent list3564 *out << Verbose(3) << "Resetting ParentList." << endl;3565 for (int i=Father->AtomCount;i--;)3566 ParentList[i] = NULL;3567 3568 // fill parent list with sons3569 *out << Verbose(3) << "Filling Parent List." << endl;3570 Walker = start;3571 while (Walker->next != end) {3572 Walker = Walker->next;3573 ParentList[Walker->father->nr] = Walker;3574 // Outputting List for debugging3575 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father <<" is " << ParentList[Walker->father->nr] << "." << endl;3576 }3577 3578 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds3579 *out << Verbose(3) << "Creating bonds." << endl;3580 Walker = Father->start;3581 while (Walker->next != Father->end) {3582 Walker = Walker->next;3583 if (ParentList[Walker->nr] != NULL) {3584 if (ParentList[Walker->nr]->father != Walker) {3585 status = false;3586 } else {3587 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) {3588 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);3589 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond3590 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl;3591 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree);3592 }3593 }3594 }3595 }3596 }3597 3598 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList");3599 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl;3600 return status;3557 atom *Walker = NULL, *OtherAtom = NULL; 3558 bool status = true; 3559 atom **ParentList = (atom **) Malloc(sizeof(atom *)*Father->AtomCount, "molecule::BuildInducedSubgraph: **ParentList"); 3560 3561 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3562 3563 // reset parent list 3564 *out << Verbose(3) << "Resetting ParentList." << endl; 3565 for (int i=Father->AtomCount;i--;) 3566 ParentList[i] = NULL; 3567 3568 // fill parent list with sons 3569 *out << Verbose(3) << "Filling Parent List." << endl; 3570 Walker = start; 3571 while (Walker->next != end) { 3572 Walker = Walker->next; 3573 ParentList[Walker->father->nr] = Walker; 3574 // Outputting List for debugging 3575 *out << Verbose(4) << "Son["<< Walker->father->nr <<"] of " << Walker->father << " is " << ParentList[Walker->father->nr] << "." << endl; 3576 } 3577 3578 // check each entry of parent list and if ok (one-to-and-onto matching) create bonds 3579 *out << Verbose(3) << "Creating bonds." << endl; 3580 Walker = Father->start; 3581 while (Walker->next != Father->end) { 3582 Walker = Walker->next; 3583 if (ParentList[Walker->nr] != NULL) { 3584 if (ParentList[Walker->nr]->father != Walker) { 3585 status = false; 3586 } else { 3587 for (int i=0;i<Father->NumberOfBondsPerAtom[Walker->nr];i++) { 3588 OtherAtom = Father->ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 3589 if (ParentList[OtherAtom->nr] != NULL) { // if otheratom is also a father of an atom on this molecule, create the bond 3590 *out << Verbose(4) << "Endpoints of Bond " << Father->ListOfBondsPerAtom[Walker->nr][i] << " are both present: " << ParentList[Walker->nr]->Name << " and " << ParentList[OtherAtom->nr]->Name << "." << endl; 3591 AddBond(ParentList[Walker->nr], ParentList[OtherAtom->nr], Father->ListOfBondsPerAtom[Walker->nr][i]->BondDegree); 3592 } 3593 } 3594 } 3595 } 3596 } 3597 3598 Free((void **)&ParentList, "molecule::BuildInducedSubgraph: **ParentList"); 3599 *out << Verbose(2) << "End of BuildInducedSubgraph." << endl; 3600 return status; 3601 3601 }; 3602 3602 … … 3610 3610 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) 3611 3611 { 3612 atom *Runner = NULL;3613 int SP, Removal;3614 3615 *out << Verbose(2) << "Looking for removal candidate." << endl;3616 SP = -1; //0;// not -1, so that Root is never removed3617 Removal = -1;3618 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) {3619 Runner = FindAtom((*runner));3620 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack3621 if (ShortestPathList[(*runner)] > SP) {// remove the oldest one with longest shortest path3622 SP = ShortestPathList[(*runner)];3623 Removal = (*runner);3624 }3625 }3626 }3627 return Removal;3612 atom *Runner = NULL; 3613 int SP, Removal; 3614 3615 *out << Verbose(2) << "Looking for removal candidate." << endl; 3616 SP = -1; //0; // not -1, so that Root is never removed 3617 Removal = -1; 3618 for (KeySet::iterator runner = Leaf->begin(); runner != Leaf->end(); runner++) { 3619 Runner = FindAtom((*runner)); 3620 if (Runner->type->Z != 1) { // skip all those added hydrogens when re-filling snake stack 3621 if (ShortestPathList[(*runner)] > SP) { // remove the oldest one with longest shortest path 3622 SP = ShortestPathList[(*runner)]; 3623 Removal = (*runner); 3624 } 3625 } 3626 } 3627 return Removal; 3628 3628 }; 3629 3629 … … 3638 3638 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 3639 3639 { 3640 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL;3641 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList");3642 molecule *Leaf = new molecule(elemente);3643 bool LonelyFlag = false;3644 int size;3645 3646 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl;3647 3648 Leaf->BondDistance = BondDistance;3649 for(int i=NDIM*2;i--;)3650 Leaf->cell_size[i] = cell_size[i];3651 3652 // initialise SonList (indicates when we need to replace a bond with hydrogen instead)3653 for(int i=AtomCount;i--;)3654 SonList[i] = NULL;3655 3656 // first create the minimal set of atoms from the KeySet3657 size = 0;3658 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {3659 FatherOfRunner = FindAtom((*runner));// find the id3660 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);3661 size++;3662 }3663 3664 // create the bonds between all: Make it an induced subgraph and add hydrogen3665 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl;3666 Runner = Leaf->start;3667 while (Runner->next != Leaf->end) {3668 Runner = Runner->next;3669 LonelyFlag = true;3670 FatherOfRunner = Runner->father;3671 if (SonList[FatherOfRunner->nr] != NULL) {// check if this, our father, is present in list3672 // create all bonds3673 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father3674 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);3675 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;3676 if (SonList[OtherFather->nr] != NULL) {3677 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl;3678 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba)3679 // *out << Verbose(3) << "Adding Bond: ";3680 // *out <<3681 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);3682 // *out << "." << endl;3683 //NumBonds[Runner->nr]++;3684 } else {3685 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl;3686 }3687 LonelyFlag = false;3688 } else {3689 // *out << ", who has no son in this fragment molecule." << endl;3640 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 3641 atom **SonList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 3642 molecule *Leaf = new molecule(elemente); 3643 bool LonelyFlag = false; 3644 int size; 3645 3646 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3647 3648 Leaf->BondDistance = BondDistance; 3649 for(int i=NDIM*2;i--;) 3650 Leaf->cell_size[i] = cell_size[i]; 3651 3652 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 3653 for(int i=AtomCount;i--;) 3654 SonList[i] = NULL; 3655 3656 // first create the minimal set of atoms from the KeySet 3657 size = 0; 3658 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 3659 FatherOfRunner = FindAtom((*runner)); // find the id 3660 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 3661 size++; 3662 } 3663 3664 // create the bonds between all: Make it an induced subgraph and add hydrogen 3665 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 3666 Runner = Leaf->start; 3667 while (Runner->next != Leaf->end) { 3668 Runner = Runner->next; 3669 LonelyFlag = true; 3670 FatherOfRunner = Runner->father; 3671 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3672 // create all bonds 3673 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3674 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3675 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3676 if (SonList[OtherFather->nr] != NULL) { 3677 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3678 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3679 // *out << Verbose(3) << "Adding Bond: "; 3680 // *out << 3681 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3682 // *out << "." << endl; 3683 //NumBonds[Runner->nr]++; 3684 } else { 3685 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3686 } 3687 LonelyFlag = false; 3688 } else { 3689 // *out << ", who has no son in this fragment molecule." << endl; 3690 3690 #ifdef ADDHYDROGEN 3691 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl;3692 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))3693 exit(1);3691 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 3692 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 3693 exit(1); 3694 3694 #endif 3695 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree;3696 }3697 }3698 } else {3699 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;3700 }3701 if ((LonelyFlag) && (size > 1)) {3702 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;3703 }3695 //NumBonds[Runner->nr] += ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree; 3696 } 3697 } 3698 } else { 3699 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 3700 } 3701 if ((LonelyFlag) && (size > 1)) { 3702 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 3703 } 3704 3704 #ifdef ADDHYDROGEN 3705 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen3706 Runner = Runner->next;3705 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3706 Runner = Runner->next; 3707 3707 #endif 3708 }3709 Leaf->CreateListOfBondsPerAtom(out);3710 //Leaflet->Leaf->ScanForPeriodicCorrection(out);3711 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList");3712 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl;3713 return Leaf;3708 } 3709 Leaf->CreateListOfBondsPerAtom(out); 3710 //Leaflet->Leaf->ScanForPeriodicCorrection(out); 3711 Free((void **)&SonList, "molecule::StoreFragmentFromStack: **SonList"); 3712 // *out << Verbose(1) << "End of StoreFragmentFromKeyset." << endl; 3713 return Leaf; 3714 3714 }; 3715 3715 … … 3717 3717 */ 3718 3718 struct UniqueFragments { 3719 config *configuration;3720 atom *Root;3721 Graph *Leaflet;3722 KeySet *FragmentSet;3723 int ANOVAOrder;3724 int FragmentCounter;3725 int CurrentIndex;3726 double TEFactor;3727 int *ShortestPathList;3728 bool **UsedList;3729 bond **BondsPerSPList;3730 int *BondsPerSPCount;3719 config *configuration; 3720 atom *Root; 3721 Graph *Leaflet; 3722 KeySet *FragmentSet; 3723 int ANOVAOrder; 3724 int FragmentCounter; 3725 int CurrentIndex; 3726 double TEFactor; 3727 int *ShortestPathList; 3728 bool **UsedList; 3729 bond **BondsPerSPList; 3730 int *BondsPerSPCount; 3731 3731 }; 3732 3732 3733 3733 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension. 3734 3734 * -# loops over every possible combination (2^dimension of edge set) 3735 * -# inserts current set, if there's still space left3736 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist3735 * -# inserts current set, if there's still space left 3736 * -# yes: calls SPFragmentGenerator with structure, created new edge list and size respective to root dist 3737 3737 ance+1 3738 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph3739 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root3738 * -# no: stores fragment into keyset list by calling InsertFragmentIntoGraph 3739 * -# removes all items added into the snake stack (in UniqueFragments structure) added during level (root 3740 3740 distance) and current set 3741 3741 * \param *out output stream for debugging … … 3747 3747 void molecule::SPFragmentGenerator(ofstream *out, struct UniqueFragments *FragmentSearch, int RootDistance, bond **BondsSet, int SetDimension, int SubOrder) 3748 3748 { 3749 atom *OtherWalker = NULL;3750 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder;3751 int NumCombinations;3752 bool bit;3753 int bits, TouchedIndex, SubSetDimension, SP, Added;3754 int Removal;3755 int SpaceLeft;3756 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList");3757 bond *Binder = NULL;3758 bond **BondsList = NULL;3759 KeySetTestPair TestKeySetInsert;3760 3761 NumCombinations = 1 << SetDimension;3762 3763 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen3764 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder3765 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden3766 3767 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl;3768 *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;3769 3770 // initialised touched list (stores added atoms on this level)3771 *out << Verbose(1+verbosity) << "Clearing touched list." << endl;3772 for (TouchedIndex=SubOrder+1;TouchedIndex--;)// empty touched list3773 TouchedList[TouchedIndex] = -1;3774 TouchedIndex = 0;3775 3776 // create every possible combination of the endpieces3777 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl;3778 for (int i=1;i<NumCombinations;i++) {// sweep through all power set combinations (skip empty set!)3779 // count the set bit of i3780 bits = 0;3781 for (int j=SetDimension;j--;)3782 bits += (i & (1 << j)) >> j;3783 3784 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl;3785 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue3786 // --1-- add this set of the power set of bond partners to the snake stack3787 Added = 0;3788 for (int j=0;j<SetDimension;j++) {// pull out every bit by shifting3789 bit = ((i & (1 << j)) != 0);// mask the bit for the j-th bond3790 if (bit) {// if bit is set, we add this bond partner3791 OtherWalker = BondsSet[j]->rightatom;// rightatom is always the one more distant, i.e. the one to add3792 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl;3793 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl;3794 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr);3795 if (TestKeySetInsert.second) {3796 TouchedList[TouchedIndex++] = OtherWalker->nr;// note as added3797 Added++;3798 } else {3799 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl;3800 }3801 //FragmentSearch->UsedList[OtherWalker->nr][i] = true;3802 //}3803 } else {3804 *out << Verbose(2+verbosity) << "Not adding." << endl;3805 }3806 }3807 3808 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore3809 if (SpaceLeft > 0) {3810 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl;3811 if (SubOrder > 1) {// Due to Added above we have to check extra whether we're not already reaching beyond the desired Order3812 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion3813 SP = RootDistance+1;// this is the next level3814 // first count the members in the subset3815 SubSetDimension = 0;3816 Binder = FragmentSearch->BondsPerSPList[2*SP];// start node for this level3817 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {// compare to end node of this level3818 Binder = Binder->next;3819 for (int k=TouchedIndex;k--;) {3820 if (Binder->Contains(TouchedList[k]))// if we added this very endpiece3821 SubSetDimension++;3822 }3823 }3824 // then allocate and fill the list3825 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList");3826 SubSetDimension = 0;3827 Binder = FragmentSearch->BondsPerSPList[2*SP];3828 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) {3829 Binder = Binder->next;3830 for (int k=0;k<TouchedIndex;k++) {3831 if (Binder->leftatom->nr == TouchedList[k])// leftatom is always the close one3832 BondsList[SubSetDimension++] = Binder;3833 }3834 }3835 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl;3836 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits);3837 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList");3838 }3839 } else {3840 // --2-- otherwise store the complete fragment3841 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl;3842 // store fragment as a KeySet3843 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: ";3844 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3845 *out << (*runner) << " ";3846 *out << endl;3847 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet))3848 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl;3849 InsertFragmentIntoGraph(out, FragmentSearch);3850 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);3851 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration);3852 }3853 3854 // --3-- remove all added items in this level from snake stack3855 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl;3856 for(int j=0;j<TouchedIndex;j++) {3857 Removal = TouchedList[j];3858 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl;3859 FragmentSearch->FragmentSet->erase(Removal);3860 TouchedList[j] = -1;3861 }3862 *out << Verbose(2) << "Remaining local nr.s on snake stack are: ";3863 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++)3864 *out << (*runner) << " ";3865 *out << endl;3866 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level3867 } else {3868 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl;3869 }3870 }3871 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList");3872 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;3749 atom *OtherWalker = NULL; 3750 int verbosity = 0; //FragmentSearch->ANOVAOrder-SubOrder; 3751 int NumCombinations; 3752 bool bit; 3753 int bits, TouchedIndex, SubSetDimension, SP, Added; 3754 int Removal; 3755 int SpaceLeft; 3756 int *TouchedList = (int *) Malloc(sizeof(int)*(SubOrder+1), "molecule::SPFragmentGenerator: *TouchedList"); 3757 bond *Binder = NULL; 3758 bond **BondsList = NULL; 3759 KeySetTestPair TestKeySetInsert; 3760 3761 NumCombinations = 1 << SetDimension; 3762 3763 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3764 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3765 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3766 3767 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3768 *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; 3769 3770 // initialised touched list (stores added atoms on this level) 3771 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3772 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3773 TouchedList[TouchedIndex] = -1; 3774 TouchedIndex = 0; 3775 3776 // create every possible combination of the endpieces 3777 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; 3778 for (int i=1;i<NumCombinations;i++) { // sweep through all power set combinations (skip empty set!) 3779 // count the set bit of i 3780 bits = 0; 3781 for (int j=SetDimension;j--;) 3782 bits += (i & (1 << j)) >> j; 3783 3784 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3785 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue 3786 // --1-- add this set of the power set of bond partners to the snake stack 3787 Added = 0; 3788 for (int j=0;j<SetDimension;j++) { // pull out every bit by shifting 3789 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3790 if (bit) { // if bit is set, we add this bond partner 3791 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3792 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3793 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3794 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3795 if (TestKeySetInsert.second) { 3796 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3797 Added++; 3798 } else { 3799 *out << Verbose(2+verbosity) << "This was item was already present in the keyset." << endl; 3800 } 3801 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3802 //} 3803 } else { 3804 *out << Verbose(2+verbosity) << "Not adding." << endl; 3805 } 3806 } 3807 3808 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3809 if (SpaceLeft > 0) { 3810 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; 3811 if (SubOrder > 1) { // Due to Added above we have to check extra whether we're not already reaching beyond the desired Order 3812 // --2-- look at all added end pieces of this combination, construct bond subsets and sweep through a power set of these by recursion 3813 SP = RootDistance+1; // this is the next level 3814 // first count the members in the subset 3815 SubSetDimension = 0; 3816 Binder = FragmentSearch->BondsPerSPList[2*SP]; // start node for this level 3817 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { // compare to end node of this level 3818 Binder = Binder->next; 3819 for (int k=TouchedIndex;k--;) { 3820 if (Binder->Contains(TouchedList[k])) // if we added this very endpiece 3821 SubSetDimension++; 3822 } 3823 } 3824 // then allocate and fill the list 3825 BondsList = (bond **) Malloc(sizeof(bond *)*SubSetDimension, "molecule::SPFragmentGenerator: **BondsList"); 3826 SubSetDimension = 0; 3827 Binder = FragmentSearch->BondsPerSPList[2*SP]; 3828 while (Binder->next != FragmentSearch->BondsPerSPList[2*SP+1]) { 3829 Binder = Binder->next; 3830 for (int k=0;k<TouchedIndex;k++) { 3831 if (Binder->leftatom->nr == TouchedList[k]) // leftatom is always the close one 3832 BondsList[SubSetDimension++] = Binder; 3833 } 3834 } 3835 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3836 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3837 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3838 } 3839 } else { 3840 // --2-- otherwise store the complete fragment 3841 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3842 // store fragment as a KeySet 3843 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3844 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3845 *out << (*runner) << " "; 3846 *out << endl; 3847 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) 3848 //*out << Verbose(0) << "ERROR: The found fragment is not a connected subgraph!" << endl; 3849 InsertFragmentIntoGraph(out, FragmentSearch); 3850 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3851 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3852 } 3853 3854 // --3-- remove all added items in this level from snake stack 3855 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; 3856 for(int j=0;j<TouchedIndex;j++) { 3857 Removal = TouchedList[j]; 3858 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3859 FragmentSearch->FragmentSet->erase(Removal); 3860 TouchedList[j] = -1; 3861 } 3862 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3863 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3864 *out << (*runner) << " "; 3865 *out << endl; 3866 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3867 } else { 3868 *out << Verbose(2+verbosity) << "More atoms to add for this set (" << bits << ") than space left on stack " << SubOrder << ", skipping this set." << endl; 3869 } 3870 } 3871 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3872 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3873 3873 }; 3874 3874 … … 3881 3881 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3882 3882 { 3883 atom *Walker = NULL, *Walker2 = NULL;3884 bool BondStatus = false;3885 int size;3886 3887 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl;3888 *out << Verbose(2) << "Disconnected atom: ";3889 3890 // count number of atoms in graph3891 size = 0;3892 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++)3893 size++;3894 if (size > 1)3895 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) {3896 Walker = FindAtom(*runner);3897 BondStatus = false;3898 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) {3899 Walker2 = FindAtom(*runners);3900 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) {3901 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) {3902 BondStatus = true;3903 break;3904 }3905 if (BondStatus)3906 break;3907 }3908 }3909 if (!BondStatus) {3910 *out << (*Walker) << endl;3911 return false;3912 }3913 }3914 else {3915 *out << "none." << endl;3916 return true;3917 }3918 *out << "none." << endl;3919 3920 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl;3921 3922 return true;3883 atom *Walker = NULL, *Walker2 = NULL; 3884 bool BondStatus = false; 3885 int size; 3886 3887 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3888 *out << Verbose(2) << "Disconnected atom: "; 3889 3890 // count number of atoms in graph 3891 size = 0; 3892 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) 3893 size++; 3894 if (size > 1) 3895 for(KeySet::iterator runner = Fragment->begin(); runner != Fragment->end(); runner++) { 3896 Walker = FindAtom(*runner); 3897 BondStatus = false; 3898 for(KeySet::iterator runners = Fragment->begin(); runners != Fragment->end(); runners++) { 3899 Walker2 = FindAtom(*runners); 3900 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr]; i++) { 3901 if (ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker) == Walker2) { 3902 BondStatus = true; 3903 break; 3904 } 3905 if (BondStatus) 3906 break; 3907 } 3908 } 3909 if (!BondStatus) { 3910 *out << (*Walker) << endl; 3911 return false; 3912 } 3913 } 3914 else { 3915 *out << "none." << endl; 3916 return true; 3917 } 3918 *out << "none." << endl; 3919 3920 *out << Verbose(1) << "End of CheckForConnectedSubgraph" << endl; 3921 3922 return true; 3923 3923 } 3924 3924 … … 3940 3940 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 3941 3941 { 3942 int SP, AtomKeyNr;3943 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL;3944 bond *Binder = NULL;3945 bond *CurrentEdge = NULL;3946 bond **BondsList = NULL;3947 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr;3948 int Counter = FragmentSearch.FragmentCounter;3949 int RemainingWalkers;3950 3951 *out << endl;3952 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl;3953 3954 // prepare Label and SP arrays of the BFS search3955 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0;3956 3957 // prepare root level (SP = 0) and a loop bond denoting Root3958 for (int i=1;i<Order;i++)3959 FragmentSearch.BondsPerSPCount[i] = 0;3960 FragmentSearch.BondsPerSPCount[0] = 1;3961 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root);3962 add(Binder, FragmentSearch.BondsPerSPList[1]);3963 3964 // do a BFS search to fill the SP lists and label the found vertices3965 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into3966 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning3967 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth3968 // (EdgeinSPLevel) of this tree ...3969 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence3970 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction.3971 *out << endl;3972 *out << Verbose(0) << "Starting BFS analysis ..." << endl;3973 for (SP = 0; SP < (Order-1); SP++) {3974 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)";3975 if (SP > 0) {3976 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl;3977 FragmentSearch.BondsPerSPCount[SP] = 0;3978 } else3979 *out << "." << endl;3980 3981 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP];3982 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP];/// start of this SP level's list3983 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) {/// end of this SP level's list3984 CurrentEdge = CurrentEdge->next;3985 RemainingWalkers--;3986 Walker = CurrentEdge->rightatom;// rightatom is always the one more distant3987 Predecessor = CurrentEdge->leftatom;// ... and leftatom is predecessor3988 AtomKeyNr = Walker->nr;3989 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl;3990 // check for new sp level3991 // go through all its bonds3992 *out << Verbose(1) << "Going through all bonds of Walker." << endl;3993 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) {3994 Binder = ListOfBondsPerAtom[AtomKeyNr][i];3995 OtherWalker = Binder->GetOtherAtom(Walker);3996 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end())3997 #ifdef ADDHYDROGEN3998 && (OtherWalker->type->Z != 1)3999 #endif4000 ) {// skip hydrogens and restrict to fragment4001 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl;4002 // set the label if not set (and push on root stack as well)4003 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's4004 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1;4005 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl;4006 // add the bond in between to the SP list4007 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant4008 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]);4009 FragmentSearch.BondsPerSPCount[SP+1]++;4010 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl;4011 } else {4012 if (OtherWalker != Predecessor)4013 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl;4014 else4015 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl;4016 }4017 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl;4018 }4019 }4020 }4021 4022 // outputting all list for debugging4023 *out << Verbose(0) << "Printing all found lists." << endl;4024 for(int i=1;i<Order;i++) {// skip the root edge in the printing4025 Binder = FragmentSearch.BondsPerSPList[2*i];4026 *out << Verbose(1) << "Current SP level is " << i << "." << endl;4027 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4028 Binder = Binder->next;4029 *out << Verbose(2) << *Binder << endl;4030 }4031 }4032 4033 // creating fragments with the found edge sets(may be done in reverse order, faster)4034 SP = -1;// the Root <-> Root edge must be subtracted!4035 for(int i=Order;i--;) { // sum up all found edges4036 Binder = FragmentSearch.BondsPerSPList[2*i];4037 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4038 Binder = Binder->next;4039 SP ++;4040 }4041 }4042 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl;4043 if (SP >= (Order-1)) {4044 // start with root (push on fragment stack)4045 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl;4046 FragmentSearch.FragmentSet->clear();4047 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl;4048 // prepare the subset and call the generator4049 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList");4050 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next;// on SP level 0 there's only the root bond4051 4052 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order);4053 4054 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList");4055 } else {4056 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl;4057 }4058 4059 // as FragmentSearch structure is used only once, we don't have to clean it anymore4060 // remove root from stack4061 *out << Verbose(0) << "Removing root again from stack." << endl;4062 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr);4063 4064 // free'ing the bonds lists4065 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl;4066 for(int i=Order;i--;) {4067 *out << Verbose(1) << "Current SP level is " << i << ": ";4068 Binder = FragmentSearch.BondsPerSPList[2*i];4069 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) {4070 Binder = Binder->next;4071 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local4072 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1;4073 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1;4074 }4075 // delete added bonds4076 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]);4077 // also start and end node4078 *out << "cleaned." << endl;4079 }4080 4081 // return list4082 *out << Verbose(0) << "End of PowerSetGenerator." << endl;4083 return (FragmentSearch.FragmentCounter - Counter);3942 int SP, AtomKeyNr; 3943 atom *Walker = NULL, *OtherWalker = NULL, *Predecessor = NULL; 3944 bond *Binder = NULL; 3945 bond *CurrentEdge = NULL; 3946 bond **BondsList = NULL; 3947 int RootKeyNr = FragmentSearch.Root->GetTrueFather()->nr; 3948 int Counter = FragmentSearch.FragmentCounter; 3949 int RemainingWalkers; 3950 3951 *out << endl; 3952 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3953 3954 // prepare Label and SP arrays of the BFS search 3955 FragmentSearch.ShortestPathList[FragmentSearch.Root->nr] = 0; 3956 3957 // prepare root level (SP = 0) and a loop bond denoting Root 3958 for (int i=1;i<Order;i++) 3959 FragmentSearch.BondsPerSPCount[i] = 0; 3960 FragmentSearch.BondsPerSPCount[0] = 1; 3961 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 3962 add(Binder, FragmentSearch.BondsPerSPList[1]); 3963 3964 // do a BFS search to fill the SP lists and label the found vertices 3965 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 3966 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 3967 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 3968 // (EdgeinSPLevel) of this tree ... 3969 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 3970 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. 3971 *out << endl; 3972 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3973 for (SP = 0; SP < (Order-1); SP++) { 3974 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with " << FragmentSearch.BondsPerSPCount[SP] << " item(s)"; 3975 if (SP > 0) { 3976 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3977 FragmentSearch.BondsPerSPCount[SP] = 0; 3978 } else 3979 *out << "." << endl; 3980 3981 RemainingWalkers = FragmentSearch.BondsPerSPCount[SP]; 3982 CurrentEdge = FragmentSearch.BondsPerSPList[2*SP]; /// start of this SP level's list 3983 while (CurrentEdge->next != FragmentSearch.BondsPerSPList[2*SP+1]) { /// end of this SP level's list 3984 CurrentEdge = CurrentEdge->next; 3985 RemainingWalkers--; 3986 Walker = CurrentEdge->rightatom; // rightatom is always the one more distant 3987 Predecessor = CurrentEdge->leftatom; // ... and leftatom is predecessor 3988 AtomKeyNr = Walker->nr; 3989 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and SP of " << SP << ", with " << RemainingWalkers << " remaining walkers on this level." << endl; 3990 // check for new sp level 3991 // go through all its bonds 3992 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3993 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3994 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3995 OtherWalker = Binder->GetOtherAtom(Walker); 3996 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3997 #ifdef ADDHYDROGEN 3998 && (OtherWalker->type->Z != 1) 3999 #endif 4000 ) { // skip hydrogens and restrict to fragment 4001 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 4002 // set the label if not set (and push on root stack as well) 4003 if ((OtherWalker != Predecessor) && (OtherWalker->GetTrueFather()->nr > RootKeyNr)) { // only pass through those with label bigger than Root's 4004 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 4005 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 4006 // add the bond in between to the SP list 4007 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 4008 add(Binder, FragmentSearch.BondsPerSPList[2*(SP+1)+1]); 4009 FragmentSearch.BondsPerSPCount[SP+1]++; 4010 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP+1] << " item(s)." << endl; 4011 } else { 4012 if (OtherWalker != Predecessor) 4013 *out << Verbose(3) << "Not passing on, as index of " << *OtherWalker << " " << OtherWalker->GetTrueFather()->nr << " is smaller than that of Root " << RootKeyNr << "." << endl; 4014 else 4015 *out << Verbose(3) << "This is my predecessor " << *Predecessor << "." << endl; 4016 } 4017 } else *out << Verbose(2) << "Is not in the restricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 4018 } 4019 } 4020 } 4021 4022 // outputting all list for debugging 4023 *out << Verbose(0) << "Printing all found lists." << endl; 4024 for(int i=1;i<Order;i++) { // skip the root edge in the printing 4025 Binder = FragmentSearch.BondsPerSPList[2*i]; 4026 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 4027 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4028 Binder = Binder->next; 4029 *out << Verbose(2) << *Binder << endl; 4030 } 4031 } 4032 4033 // creating fragments with the found edge sets (may be done in reverse order, faster) 4034 SP = -1; // the Root <-> Root edge must be subtracted! 4035 for(int i=Order;i--;) { // sum up all found edges 4036 Binder = FragmentSearch.BondsPerSPList[2*i]; 4037 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4038 Binder = Binder->next; 4039 SP ++; 4040 } 4041 } 4042 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 4043 if (SP >= (Order-1)) { 4044 // start with root (push on fragment stack) 4045 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4046 FragmentSearch.FragmentSet->clear(); 4047 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4048 // prepare the subset and call the generator 4049 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4050 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4051 4052 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4053 4054 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4055 } else { 4056 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 4057 } 4058 4059 // as FragmentSearch structure is used only once, we don't have to clean it anymore 4060 // remove root from stack 4061 *out << Verbose(0) << "Removing root again from stack." << endl; 4062 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4063 4064 // free'ing the bonds lists 4065 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 4066 for(int i=Order;i--;) { 4067 *out << Verbose(1) << "Current SP level is " << i << ": "; 4068 Binder = FragmentSearch.BondsPerSPList[2*i]; 4069 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4070 Binder = Binder->next; 4071 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 4072 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 4073 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 4074 } 4075 // delete added bonds 4076 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 4077 // also start and end node 4078 *out << "cleaned." << endl; 4079 } 4080 4081 // return list 4082 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4083 return (FragmentSearch.FragmentCounter - Counter); 4084 4084 }; 4085 4085 … … 4092 4092 void molecule::ScanForPeriodicCorrection(ofstream *out) 4093 4093 { 4094 bond *Binder = NULL;4095 bond *OtherBinder = NULL;4096 atom *Walker = NULL;4097 atom *OtherWalker = NULL;4098 double *matrix = ReturnFullMatrixforSymmetric(cell_size);4099 enum Shading *ColorList = NULL;4100 double tmp;4101 Vector Translationvector;4102 //class StackClass<atom *> *CompStack = NULL;4103 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount);4104 bool flag = true;4105 4106 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl;4107 4108 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList");4109 while (flag) {4110 // remove bonds that are beyond bonddistance4111 for(int i=NDIM;i--;)4112 Translationvector.x[i] = 0.;4113 // scan all bonds4114 Binder = first;4115 flag = false;4116 while ((!flag) && (Binder->next != last)) {4117 Binder = Binder->next;4118 for (int i=NDIM;i--;) {4119 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]);4120 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl;4121 if (tmp > BondDistance) {4122 OtherBinder = Binder->next; // note down binding partner for later re-insertion4123 unlink(Binder);// unlink bond4124 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl;4125 flag = true;4126 break;4127 }4128 }4129 }4130 if (flag) {4131 // create translation vector from their periodically modified distance4132 for (int i=NDIM;i--;) {4133 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i];4134 if (fabs(tmp) > BondDistance)4135 Translationvector.x[i] = (tmp < 0) ? +1. : -1.;4136 }4137 Translationvector.MatrixMultiplication(matrix);4138 //*out << Verbose(3) << "Translation vector is ";4139 Translationvector.Output(out);4140 *out << endl;4141 // apply to all atoms of first component via BFS4142 for (int i=AtomCount;i--;)4143 ColorList[i] = white;4144 AtomStack->Push(Binder->leftatom);4145 while (!AtomStack->IsEmpty()) {4146 Walker = AtomStack->PopFirst();4147 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl;4148 ColorList[Walker->nr] = black;// mark as explored4149 Walker->x.AddVector(&Translationvector); // translate4150 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {// go through all binding partners4151 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) {4152 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);4153 if (ColorList[OtherWalker->nr] == white) {4154 AtomStack->Push(OtherWalker); // push if yet unexplored4155 }4156 }4157 }4158 }4159 // re-add bond4160 link(Binder, OtherBinder);4161 } else {4162 *out << Verbose(3) << "No corrections for this fragment." << endl;4163 }4164 //delete(CompStack);4165 }4166 4167 // free allocated space from ReturnFullMatrixforSymmetric()4168 delete(AtomStack);4169 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList");4170 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix");4171 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl;4094 bond *Binder = NULL; 4095 bond *OtherBinder = NULL; 4096 atom *Walker = NULL; 4097 atom *OtherWalker = NULL; 4098 double *matrix = ReturnFullMatrixforSymmetric(cell_size); 4099 enum Shading *ColorList = NULL; 4100 double tmp; 4101 Vector Translationvector; 4102 //class StackClass<atom *> *CompStack = NULL; 4103 class StackClass<atom *> *AtomStack = new StackClass<atom *>(AtomCount); 4104 bool flag = true; 4105 4106 *out << Verbose(2) << "Begin of ScanForPeriodicCorrection." << endl; 4107 4108 ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::ScanForPeriodicCorrection: *ColorList"); 4109 while (flag) { 4110 // remove bonds that are beyond bonddistance 4111 for(int i=NDIM;i--;) 4112 Translationvector.x[i] = 0.; 4113 // scan all bonds 4114 Binder = first; 4115 flag = false; 4116 while ((!flag) && (Binder->next != last)) { 4117 Binder = Binder->next; 4118 for (int i=NDIM;i--;) { 4119 tmp = fabs(Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]); 4120 //*out << Verbose(3) << "Checking " << i << "th distance of " << *Binder->leftatom << " to " << *Binder->rightatom << ": " << tmp << "." << endl; 4121 if (tmp > BondDistance) { 4122 OtherBinder = Binder->next; // note down binding partner for later re-insertion 4123 unlink(Binder); // unlink bond 4124 *out << Verbose(2) << "Correcting at bond " << *Binder << "." << endl; 4125 flag = true; 4126 break; 4127 } 4128 } 4129 } 4130 if (flag) { 4131 // create translation vector from their periodically modified distance 4132 for (int i=NDIM;i--;) { 4133 tmp = Binder->leftatom->x.x[i] - Binder->rightatom->x.x[i]; 4134 if (fabs(tmp) > BondDistance) 4135 Translationvector.x[i] = (tmp < 0) ? +1. : -1.; 4136 } 4137 Translationvector.MatrixMultiplication(matrix); 4138 //*out << Verbose(3) << "Translation vector is "; 4139 Translationvector.Output(out); 4140 *out << endl; 4141 // apply to all atoms of first component via BFS 4142 for (int i=AtomCount;i--;) 4143 ColorList[i] = white; 4144 AtomStack->Push(Binder->leftatom); 4145 while (!AtomStack->IsEmpty()) { 4146 Walker = AtomStack->PopFirst(); 4147 //*out << Verbose (3) << "Current Walker is: " << *Walker << "." << endl; 4148 ColorList[Walker->nr] = black; // mark as explored 4149 Walker->x.AddVector(&Translationvector); // translate 4150 for (int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through all binding partners 4151 if (ListOfBondsPerAtom[Walker->nr][i] != Binder) { 4152 OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); 4153 if (ColorList[OtherWalker->nr] == white) { 4154 AtomStack->Push(OtherWalker); // push if yet unexplored 4155 } 4156 } 4157 } 4158 } 4159 // re-add bond 4160 link(Binder, OtherBinder); 4161 } else { 4162 *out << Verbose(3) << "No corrections for this fragment." << endl; 4163 } 4164 //delete(CompStack); 4165 } 4166 4167 // free allocated space from ReturnFullMatrixforSymmetric() 4168 delete(AtomStack); 4169 Free((void **)&ColorList, "molecule::ScanForPeriodicCorrection: *ColorList"); 4170 Free((void **)&matrix, "molecule::ScanForPeriodicCorrection: *matrix"); 4171 *out << Verbose(2) << "End of ScanForPeriodicCorrection." << endl; 4172 4172 }; 4173 4173 … … 4178 4178 double * molecule::ReturnFullMatrixforSymmetric(double *symm) 4179 4179 { 4180 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix");4181 matrix[0] = symm[0];4182 matrix[1] = symm[1];4183 matrix[2] = symm[2];4184 matrix[3] = symm[1];4185 matrix[4] = symm[3];4186 matrix[5] = symm[4];4187 matrix[6] = symm[2];4188 matrix[7] = symm[4];4189 matrix[8] = symm[5];4190 return matrix;4180 double *matrix = (double *) Malloc(sizeof(double)*NDIM*NDIM, "molecule::ReturnFullMatrixforSymmetric: *matrix"); 4181 matrix[0] = symm[0]; 4182 matrix[1] = symm[1]; 4183 matrix[2] = symm[2]; 4184 matrix[3] = symm[1]; 4185 matrix[4] = symm[3]; 4186 matrix[5] = symm[4]; 4187 matrix[6] = symm[2]; 4188 matrix[7] = symm[4]; 4189 matrix[8] = symm[5]; 4190 return matrix; 4191 4191 }; 4192 4192 4193 4193 bool KeyCompare::operator() (const KeySet SubgraphA, const KeySet SubgraphB) const 4194 4194 { 4195 //cout << "my check is used." << endl;4196 if (SubgraphA.size() < SubgraphB.size()) {4197 return true;4198 } else {4199 if (SubgraphA.size() > SubgraphB.size()) {4200 return false;4201 } else {4202 KeySet::iterator IteratorA = SubgraphA.begin();4203 KeySet::iterator IteratorB = SubgraphB.begin();4204 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) {4205 if ((*IteratorA) <(*IteratorB))4206 return true;4207 else if ((*IteratorA) > (*IteratorB)) {4208 return false;4209 } // else, go on to next index4210 IteratorA++;4211 IteratorB++;4212 } // end of while loop4213 }// end of check in case of equal sizes4214 }4215 return false; // if we reach this point, they are equal4195 //cout << "my check is used." << endl; 4196 if (SubgraphA.size() < SubgraphB.size()) { 4197 return true; 4198 } else { 4199 if (SubgraphA.size() > SubgraphB.size()) { 4200 return false; 4201 } else { 4202 KeySet::iterator IteratorA = SubgraphA.begin(); 4203 KeySet::iterator IteratorB = SubgraphB.begin(); 4204 while ((IteratorA != SubgraphA.end()) && (IteratorB != SubgraphB.end())) { 4205 if ((*IteratorA) < (*IteratorB)) 4206 return true; 4207 else if ((*IteratorA) > (*IteratorB)) { 4208 return false; 4209 } // else, go on to next index 4210 IteratorA++; 4211 IteratorB++; 4212 } // end of while loop 4213 }// end of check in case of equal sizes 4214 } 4215 return false; // if we reach this point, they are equal 4216 4216 }; 4217 4217 4218 4218 //bool operator < (KeySet SubgraphA, KeySet SubgraphB) 4219 4219 //{ 4220 // return KeyCompare(SubgraphA, SubgraphB);4220 // return KeyCompare(SubgraphA, SubgraphB); 4221 4221 //}; 4222 4222 … … 4230 4230 inline void InsertFragmentIntoGraph(ofstream *out, struct UniqueFragments *Fragment) 4231 4231 { 4232 GraphTestPair testGraphInsert;4233 4234 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor)));// store fragment number and current factor4235 if (testGraphInsert.second) {4236 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl;4237 Fragment->FragmentCounter++;4238 } else {4239 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4240 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor;// increase the "created" counter4241 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl;4242 }4232 GraphTestPair testGraphInsert; 4233 4234 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,Fragment->TEFactor))); // store fragment number and current factor 4235 if (testGraphInsert.second) { 4236 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; 4237 Fragment->FragmentCounter++; 4238 } else { 4239 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4240 ((*(testGraphInsert.first)).second).second += Fragment->TEFactor; // increase the "created" counter 4241 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 4242 } 4243 4243 }; 4244 4244 //void inline InsertIntoGraph(ofstream *out, KeyStack &stack, Graph &graph, int *counter, double factor) 4245 4245 //{ 4246 // // copy stack contents to set and call overloaded function again4247 // KeySet set;4248 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++)4249 // set.insert((*runner));4250 // InsertIntoGraph(out, set, graph, counter, factor);4246 // // copy stack contents to set and call overloaded function again 4247 // KeySet set; 4248 // for(KeyStack::iterator runner = stack.begin(); runner != stack.begin(); runner++) 4249 // set.insert((*runner)); 4250 // InsertIntoGraph(out, set, graph, counter, factor); 4251 4251 //}; 4252 4252 … … 4259 4259 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) 4260 4260 { 4261 GraphTestPair testGraphInsert;4262 4263 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) {4264 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second)));// store fragment number and current factor4265 if (testGraphInsert.second) {4266 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl;4267 } else {4268 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl;4269 ((*(testGraphInsert.first)).second).second += (*runner).second.second;4270 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl;4271 }4272 }4261 GraphTestPair testGraphInsert; 4262 4263 for(Graph::iterator runner = graph2.begin(); runner != graph2.end(); runner++) { 4264 testGraphInsert = graph1.insert(GraphPair ((*runner).first,pair<int,double>((*counter)++,((*runner).second).second))); // store fragment number and current factor 4265 if (testGraphInsert.second) { 4266 *out << Verbose(2) << "KeySet " << (*counter)-1 << " successfully inserted." << endl; 4267 } else { 4268 *out << Verbose(2) << "KeySet " << (*counter)-1 << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 4269 ((*(testGraphInsert.first)).second).second += (*runner).second.second; 4270 *out << Verbose(2) << "New factor is " << (*(testGraphInsert.first)).second.second << "." << endl; 4271 } 4272 } 4273 4273 }; 4274 4274 … … 4277 4277 * -# constructs a complete keyset of the molecule 4278 4278 * -# In a loop over all possible roots from the given rootstack 4279 * -# increases order of root site4280 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr4281 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset4279 * -# increases order of root site 4280 * -# calls PowerSetGenerator with this order, the complete keyset and the rootkeynr 4281 * -# for all consecutive lower levels PowerSetGenerator is called with the suborder, the higher order keyset 4282 4282 as the restricted one and each site in the set as the root) 4283 * -# these are merged into a fragment list of keysets4283 * -# these are merged into a fragment list of keysets 4284 4284 * -# All fragment lists (for all orders, i.e. from all destination fields) are merged into one list for return 4285 4285 * Important only is that we create all fragments, it is not important if we create them more than once … … 4293 4293 void molecule::FragmentBOSSANOVA(ofstream *out, Graph *&FragmentList, KeyStack &RootStack, int *MinimumRingSize) 4294 4294 { 4295 Graph ***FragmentLowerOrdersList = NULL;4296 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;4297 int counter = 0, Order;4298 int UpgradeCount = RootStack.size();4299 KeyStack FragmentRootStack;4300 int RootKeyNr, RootNr;4301 struct UniqueFragments FragmentSearch;4302 4303 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl;4304 4305 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)4306 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5)4307 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4308 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4309 4310 // initialise the fragments structure4311 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");4312 FragmentSearch.FragmentCounter = 0;4313 FragmentSearch.FragmentSet = new KeySet;4314 FragmentSearch.Root = FindAtom(RootKeyNr);4315 for (int i=AtomCount;i--;) {4316 FragmentSearch.ShortestPathList[i] = -1;4317 }4318 4319 // Construct the complete KeySet which we need for topmost level only (but for all Roots)4320 atom *Walker = start;4321 KeySet CompleteMolecule;4322 while (Walker->next != end) {4323 Walker = Walker->next;4324 CompleteMolecule.insert(Walker->GetTrueFather()->nr);4325 }4326 4327 // 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, as4328 // 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),4329 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[])4330 // 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)4331 RootNr = 0;// counts through the roots in RootStack4332 while ((RootNr < UpgradeCount) && (!RootStack.empty())) {4333 RootKeyNr = RootStack.front();4334 RootStack.pop_front();4335 Walker = FindAtom(RootKeyNr);4336 // check cyclic lengths4337 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) {4338 //*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;4339 //} else4340 {4341 // increase adaptive order by one4342 Walker->GetTrueFather()->AdaptiveOrder++;4343 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder;4344 4345 // initialise Order-dependent entries of UniqueFragments structure4346 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");4347 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");4348 for (int i=Order;i--;) {4349 FragmentSearch.BondsPerSPList[2*i] = new bond();// start node4350 FragmentSearch.BondsPerSPList[2*i+1] = new bond();// end node4351 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1];// intertwine these two4352 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i];4353 FragmentSearch.BondsPerSPCount[i] = 0;4354 }4355 4356 // allocate memory for all lower level orders in this 1D-array of ptrs4357 NumLevels = 1 << (Order-1); // (int)pow(2,Order);4358 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4359 for (int i=0;i<NumLevels;i++)4360 FragmentLowerOrdersList[RootNr][i] = NULL;4361 4362 // create top order where nothing is reduced4363 *out << Verbose(0) << "==============================================================================================================" << endl;4364 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << "4365 4366 // Create list of Graphs of current Bond Order (i.e. F_{ij})4367 FragmentLowerOrdersList[RootNr][0] =new Graph;4368 FragmentSearch.TEFactor = 1.;4369 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0];// set to insertion graph4370 FragmentSearch.Root = Walker;4371 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule);4372 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4373 if (NumMoleculesOfOrder[RootNr] != 0) {4374 NumMolecules = 0;4375 4376 // we don't have to dive into suborders! These keysets are all already created on lower orders!4377 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed)4378 4379 // if ((NumLevels >> 1) > 0) {4380 // // create lower order fragments4381 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl;4382 // Order = Walker->AdaptiveOrder;4383 // 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)4384 // // step down to next order at (virtual) boundary of powers of 2 in array4385 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order))4386 // Order--;4387 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl;4388 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) {4389 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1)));4390 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl;4391 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl;4295 Graph ***FragmentLowerOrdersList = NULL; 4296 int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 4297 int counter = 0, Order; 4298 int UpgradeCount = RootStack.size(); 4299 KeyStack FragmentRootStack; 4300 int RootKeyNr, RootNr; 4301 struct UniqueFragments FragmentSearch; 4302 4303 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4304 4305 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 4306 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 4307 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4308 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4309 4310 // initialise the fragments structure 4311 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 4312 FragmentSearch.FragmentCounter = 0; 4313 FragmentSearch.FragmentSet = new KeySet; 4314 FragmentSearch.Root = FindAtom(RootKeyNr); 4315 for (int i=AtomCount;i--;) { 4316 FragmentSearch.ShortestPathList[i] = -1; 4317 } 4318 4319 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 4320 atom *Walker = start; 4321 KeySet CompleteMolecule; 4322 while (Walker->next != end) { 4323 Walker = Walker->next; 4324 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4325 } 4326 4327 // 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 4328 // 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), 4329 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 4330 // 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) 4331 RootNr = 0; // counts through the roots in RootStack 4332 while ((RootNr < UpgradeCount) && (!RootStack.empty())) { 4333 RootKeyNr = RootStack.front(); 4334 RootStack.pop_front(); 4335 Walker = FindAtom(RootKeyNr); 4336 // check cyclic lengths 4337 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4338 // *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; 4339 //} else 4340 { 4341 // increase adaptive order by one 4342 Walker->GetTrueFather()->AdaptiveOrder++; 4343 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4344 4345 // initialise Order-dependent entries of UniqueFragments structure 4346 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4347 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4348 for (int i=Order;i--;) { 4349 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4350 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4351 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4352 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4353 FragmentSearch.BondsPerSPCount[i] = 0; 4354 } 4355 4356 // allocate memory for all lower level orders in this 1D-array of ptrs 4357 NumLevels = 1 << (Order-1); // (int)pow(2,Order); 4358 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4359 for (int i=0;i<NumLevels;i++) 4360 FragmentLowerOrdersList[RootNr][i] = NULL; 4361 4362 // create top order where nothing is reduced 4363 *out << Verbose(0) << "==============================================================================================================" << endl; 4364 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4365 4366 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4367 FragmentLowerOrdersList[RootNr][0] = new Graph; 4368 FragmentSearch.TEFactor = 1.; 4369 FragmentSearch.Leaflet = FragmentLowerOrdersList[RootNr][0]; // set to insertion graph 4370 FragmentSearch.Root = Walker; 4371 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentSearch, CompleteMolecule); 4372 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4373 if (NumMoleculesOfOrder[RootNr] != 0) { 4374 NumMolecules = 0; 4375 4376 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4377 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4378 4379 // if ((NumLevels >> 1) > 0) { 4380 // // create lower order fragments 4381 // *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 4382 // Order = Walker->AdaptiveOrder; 4383 // 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) 4384 // // step down to next order at (virtual) boundary of powers of 2 in array 4385 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4386 // Order--; 4387 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 4388 // for (int SubOrder=Order-1;SubOrder>0;SubOrder--) { 4389 // int dest = source + (1 << (Walker->AdaptiveOrder-(SubOrder+1))); 4390 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4391 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4392 4392 // 4393 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules4394 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl;4395 // //NumMolecules = 0;4396 // FragmentLowerOrdersList[RootNr][dest] = new Graph;4397 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) {4398 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) {4399 // Graph TempFragmentList;4400 // FragmentSearch.TEFactor = -(*runner).second.second;4401 // FragmentSearch.Leaflet = &TempFragmentList;// set to insertion graph4402 // FragmentSearch.Root = FindAtom(*sprinter);4403 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first);4404 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest]4405 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl;4406 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules);4407 // }4408 // }4409 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl;4410 // }4411 // }4412 // }4413 } else {4414 Walker->GetTrueFather()->MaxOrder = true;4415 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl;4416 }4417 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder4418 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules;4419 TotalNumMolecules += NumMoleculesOfOrder[RootNr];4420 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl;4421 RootStack.push_back(RootKeyNr); // put back on stack4422 RootNr++;4423 4424 // free Order-dependent entries of UniqueFragments structure for next loop cycle4425 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount");4426 for (int i=Order;i--;) {4427 delete(FragmentSearch.BondsPerSPList[2*i]);4428 delete(FragmentSearch.BondsPerSPList[2*i+1]);4429 }4430 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList");4431 }4432 }4433 *out << Verbose(0) << "==============================================================================================================" << endl;4434 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl;4435 *out << Verbose(0) << "==============================================================================================================" << endl;4436 4437 // cleanup FragmentSearch structure4438 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList");4439 delete(FragmentSearch.FragmentSet);4440 4441 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein)4442 // 54332222111111114443 // 432211114444 // 32114445 // 214446 // 14447 4448 // Subsequently, we combine all into a single list (FragmentList)4449 4450 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl;4451 if (FragmentList == NULL) {4452 FragmentList = new Graph;4453 counter = 0;4454 } else {4455 counter = FragmentList->size();4456 }4457 RootNr = 0;4458 while (!RootStack.empty()) {4459 RootKeyNr = RootStack.front();4460 RootStack.pop_front();4461 Walker = FindAtom(RootKeyNr);4462 NumLevels = 1 << (Walker->AdaptiveOrder - 1);4463 for(int i=0;i<NumLevels;i++) {4464 if (FragmentLowerOrdersList[RootNr][i] != NULL) {4465 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter);4466 delete(FragmentLowerOrdersList[RootNr][i]);4467 }4468 }4469 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]");4470 RootNr++;4471 }4472 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");4473 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");4474 4475 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl;4393 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4394 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 4395 // //NumMolecules = 0; 4396 // FragmentLowerOrdersList[RootNr][dest] = new Graph; 4397 // for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 4398 // for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 4399 // Graph TempFragmentList; 4400 // FragmentSearch.TEFactor = -(*runner).second.second; 4401 // FragmentSearch.Leaflet = &TempFragmentList; // set to insertion graph 4402 // FragmentSearch.Root = FindAtom(*sprinter); 4403 // NumMoleculesOfOrder[RootNr] += PowerSetGenerator(out, SubOrder, FragmentSearch, (*runner).first); 4404 // // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 4405 // *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 4406 // InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], TempFragmentList, &NumMolecules); 4407 // } 4408 // } 4409 // *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 4410 // } 4411 // } 4412 // } 4413 } else { 4414 Walker->GetTrueFather()->MaxOrder = true; 4415 // *out << Verbose(1) << "Hence, we don't dive into SubOrders ... " << endl; 4416 } 4417 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 4418 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 4419 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 4420 // *out << Verbose(1) << "Number of resulting molecules for Order " << (int)Walker->GetTrueFather()->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 4421 RootStack.push_back(RootKeyNr); // put back on stack 4422 RootNr++; 4423 4424 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4425 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 4426 for (int i=Order;i--;) { 4427 delete(FragmentSearch.BondsPerSPList[2*i]); 4428 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4429 } 4430 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4431 } 4432 } 4433 *out << Verbose(0) << "==============================================================================================================" << endl; 4434 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 4435 *out << Verbose(0) << "==============================================================================================================" << endl; 4436 4437 // cleanup FragmentSearch structure 4438 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4439 delete(FragmentSearch.FragmentSet); 4440 4441 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4442 // 5433222211111111 4443 // 43221111 4444 // 3211 4445 // 21 4446 // 1 4447 4448 // Subsequently, we combine all into a single list (FragmentList) 4449 4450 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 4451 if (FragmentList == NULL) { 4452 FragmentList = new Graph; 4453 counter = 0; 4454 } else { 4455 counter = FragmentList->size(); 4456 } 4457 RootNr = 0; 4458 while (!RootStack.empty()) { 4459 RootKeyNr = RootStack.front(); 4460 RootStack.pop_front(); 4461 Walker = FindAtom(RootKeyNr); 4462 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4463 for(int i=0;i<NumLevels;i++) { 4464 if (FragmentLowerOrdersList[RootNr][i] != NULL) { 4465 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 4466 delete(FragmentLowerOrdersList[RootNr][i]); 4467 } 4468 } 4469 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 4470 RootNr++; 4471 } 4472 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4473 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4474 4475 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4476 4476 }; 4477 4477 … … 4483 4483 inline int CompareDoubles (const void * a, const void * b) 4484 4484 { 4485 if (*(double *)a > *(double *)b)4486 return -1;4487 else if (*(double *)a < *(double *)b)4488 return 1;4489 else4490 return 0;4485 if (*(double *)a > *(double *)b) 4486 return -1; 4487 else if (*(double *)a < *(double *)b) 4488 return 1; 4489 else 4490 return 0; 4491 4491 }; 4492 4492 … … 4499 4499 int * molecule::IsEqualToWithinThreshold(ofstream *out, molecule *OtherMolecule, double threshold) 4500 4500 { 4501 int flag;4502 double *Distances = NULL, *OtherDistances = NULL;4503 Vector CenterOfGravity, OtherCenterOfGravity;4504 size_t *PermMap = NULL, *OtherPermMap = NULL;4505 int *PermutationMap = NULL;4506 atom *Walker = NULL;4507 bool result = true; // status of comparison4508 4509 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl;4510 /// first count both their atoms and elements and update lists thereby ...4511 //*out << Verbose(0) << "Counting atoms, updating list" << endl;4512 CountAtoms(out);4513 OtherMolecule->CountAtoms(out);4514 CountElements();4515 OtherMolecule->CountElements();4516 4517 /// ... and compare:4518 /// -# AtomCount4519 if (result) {4520 if (AtomCount != OtherMolecule->AtomCount) {4521 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4522 result = false;4523 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl;4524 }4525 /// -# ElementCount4526 if (result) {4527 if (ElementCount != OtherMolecule->ElementCount) {4528 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4529 result = false;4530 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl;4531 }4532 /// -# ElementsInMolecule4533 if (result) {4534 for (flag=MAX_ELEMENTS;flag--;) {4535 //*out << Verbose(5) << "Element " <<flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl;4536 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag])4537 break;4538 }4539 if (flag < MAX_ELEMENTS) {4540 *out << Verbose(4) << "ElementsInMolecule don't match." << endl;4541 result = false;4542 } else *out << Verbose(4) << "ElementsInMolecule match." << endl;4543 }4544 /// then determine and compare center of gravity for each molecule ...4545 if (result) {4546 *out << Verbose(5) << "Calculating Centers of Gravity" << endl;4547 DetermineCenter(CenterOfGravity);4548 OtherMolecule->DetermineCenter(OtherCenterOfGravity);4549 *out << Verbose(5) << "Center of Gravity: ";4550 CenterOfGravity.Output(out);4551 *out << endl << Verbose(5) << "Other Center of Gravity: ";4552 OtherCenterOfGravity.Output(out);4553 *out << endl;4554 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) {4555 *out << Verbose(4) << "Centers of gravity don't match." << endl;4556 result = false;4557 }4558 }4559 4560 /// ... then make a list with the euclidian distance to this center for each atom of both molecules4561 if (result) {4562 *out << Verbose(5) << "Calculating distances" << endl;4563 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances");4564 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances");4565 Walker = start;4566 while (Walker->next != end) {4567 Walker = Walker->next;4568 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x);4569 }4570 Walker = OtherMolecule->start;4571 while (Walker->next != OtherMolecule->end) {4572 Walker = Walker->next;4573 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x);4574 }4575 4576 /// ... sort each list (using heapsort (o(N log N)) from GSL)4577 *out << Verbose(5) << "Sorting distances" << endl;4578 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap");4579 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4580 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles);4581 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles);4582 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap");4583 *out << Verbose(5) << "Combining Permutation Maps" << endl;4584 for(int i=AtomCount;i--;)4585 PermutationMap[PermMap[i]] = (int) OtherPermMap[i];4586 4587 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all4588 *out << Verbose(4) << "Comparing distances" << endl;4589 flag = 0;4590 for (int i=0;i<AtomCount;i++) {4591 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " <<threshold << endl;4592 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold)4593 flag = 1;4594 }4595 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap");4596 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap");4597 4598 /// free memory4599 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances");4600 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances");4601 if (flag) { // if not equal4602 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap");4603 result = false;4604 }4605 }4606 /// return pointer to map if all distances were below \a threshold4607 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl;4608 if (result) {4609 *out << Verbose(3) << "Result: Equal." << endl;4610 return PermutationMap;4611 } else {4612 *out << Verbose(3) << "Result: Not equal." << endl;4613 return NULL;4614 }4501 int flag; 4502 double *Distances = NULL, *OtherDistances = NULL; 4503 Vector CenterOfGravity, OtherCenterOfGravity; 4504 size_t *PermMap = NULL, *OtherPermMap = NULL; 4505 int *PermutationMap = NULL; 4506 atom *Walker = NULL; 4507 bool result = true; // status of comparison 4508 4509 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4510 /// first count both their atoms and elements and update lists thereby ... 4511 //*out << Verbose(0) << "Counting atoms, updating list" << endl; 4512 CountAtoms(out); 4513 OtherMolecule->CountAtoms(out); 4514 CountElements(); 4515 OtherMolecule->CountElements(); 4516 4517 /// ... and compare: 4518 /// -# AtomCount 4519 if (result) { 4520 if (AtomCount != OtherMolecule->AtomCount) { 4521 *out << Verbose(4) << "AtomCounts don't match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4522 result = false; 4523 } else *out << Verbose(4) << "AtomCounts match: " << AtomCount << " == " << OtherMolecule->AtomCount << endl; 4524 } 4525 /// -# ElementCount 4526 if (result) { 4527 if (ElementCount != OtherMolecule->ElementCount) { 4528 *out << Verbose(4) << "ElementCount don't match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4529 result = false; 4530 } else *out << Verbose(4) << "ElementCount match: " << ElementCount << " == " << OtherMolecule->ElementCount << endl; 4531 } 4532 /// -# ElementsInMolecule 4533 if (result) { 4534 for (flag=MAX_ELEMENTS;flag--;) { 4535 //*out << Verbose(5) << "Element " << flag << ": " << ElementsInMolecule[flag] << " <-> " << OtherMolecule->ElementsInMolecule[flag] << "." << endl; 4536 if (ElementsInMolecule[flag] != OtherMolecule->ElementsInMolecule[flag]) 4537 break; 4538 } 4539 if (flag < MAX_ELEMENTS) { 4540 *out << Verbose(4) << "ElementsInMolecule don't match." << endl; 4541 result = false; 4542 } else *out << Verbose(4) << "ElementsInMolecule match." << endl; 4543 } 4544 /// then determine and compare center of gravity for each molecule ... 4545 if (result) { 4546 *out << Verbose(5) << "Calculating Centers of Gravity" << endl; 4547 DetermineCenter(CenterOfGravity); 4548 OtherMolecule->DetermineCenter(OtherCenterOfGravity); 4549 *out << Verbose(5) << "Center of Gravity: "; 4550 CenterOfGravity.Output(out); 4551 *out << endl << Verbose(5) << "Other Center of Gravity: "; 4552 OtherCenterOfGravity.Output(out); 4553 *out << endl; 4554 if (CenterOfGravity.DistanceSquared(&OtherCenterOfGravity) > threshold*threshold) { 4555 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4556 result = false; 4557 } 4558 } 4559 4560 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4561 if (result) { 4562 *out << Verbose(5) << "Calculating distances" << endl; 4563 Distances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: Distances"); 4564 OtherDistances = (double *) Malloc(sizeof(double)*AtomCount, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4565 Walker = start; 4566 while (Walker->next != end) { 4567 Walker = Walker->next; 4568 Distances[Walker->nr] = CenterOfGravity.DistanceSquared(&Walker->x); 4569 } 4570 Walker = OtherMolecule->start; 4571 while (Walker->next != OtherMolecule->end) { 4572 Walker = Walker->next; 4573 OtherDistances[Walker->nr] = OtherCenterOfGravity.DistanceSquared(&Walker->x); 4574 } 4575 4576 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4577 *out << Verbose(5) << "Sorting distances" << endl; 4578 PermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermMap"); 4579 OtherPermMap = (size_t *) Malloc(sizeof(size_t)*AtomCount, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4580 gsl_heapsort_index (PermMap, Distances, AtomCount, sizeof(double), CompareDoubles); 4581 gsl_heapsort_index (OtherPermMap, OtherDistances, AtomCount, sizeof(double), CompareDoubles); 4582 PermutationMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4583 *out << Verbose(5) << "Combining Permutation Maps" << endl; 4584 for(int i=AtomCount;i--;) 4585 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4586 4587 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4588 *out << Verbose(4) << "Comparing distances" << endl; 4589 flag = 0; 4590 for (int i=0;i<AtomCount;i++) { 4591 *out << Verbose(5) << "Distances squared: |" << Distances[PermMap[i]] << " - " << OtherDistances[OtherPermMap[i]] << "| = " << fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) << " ?<? " << threshold << endl; 4592 if (fabs(Distances[PermMap[i]] - OtherDistances[OtherPermMap[i]]) > threshold*threshold) 4593 flag = 1; 4594 } 4595 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4596 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4597 4598 /// free memory 4599 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); 4600 Free((void **)&OtherDistances, "molecule::IsEqualToWithinThreshold: OtherDistances"); 4601 if (flag) { // if not equal 4602 Free((void **)&PermutationMap, "molecule::IsEqualToWithinThreshold: *PermutationMap"); 4603 result = false; 4604 } 4605 } 4606 /// return pointer to map if all distances were below \a threshold 4607 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; 4608 if (result) { 4609 *out << Verbose(3) << "Result: Equal." << endl; 4610 return PermutationMap; 4611 } else { 4612 *out << Verbose(3) << "Result: Not equal." << endl; 4613 return NULL; 4614 } 4615 4615 }; 4616 4616 … … 4624 4624 int * molecule::GetFatherSonAtomicMap(ofstream *out, molecule *OtherMolecule) 4625 4625 { 4626 atom *Walker = NULL, *OtherWalker = NULL;4627 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl;4628 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap");//Calloc4629 for (int i=AtomCount;i--;)4630 AtomicMap[i] = -1;4631 if (OtherMolecule == this) {// same molecule4632 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence4633 AtomicMap[i] = i;4634 *out << Verbose(4) << "Map is trivial." << endl;4635 } else {4636 *out << Verbose(4) << "Map is ";4637 Walker = start;4638 while (Walker->next != end) {4639 Walker = Walker->next;4640 if (Walker->father == NULL) {4641 AtomicMap[Walker->nr] = -2;4642 } else {4643 OtherWalker = OtherMolecule->start;4644 while (OtherWalker->next != OtherMolecule->end) {4645 OtherWalker = OtherWalker->next;4646 //for (int i=0;i<AtomCount;i++) { // search atom4647 //for (int j=0;j<OtherMolecule->AtomCount;j++) {4648 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl;4649 if (Walker->father == OtherWalker)4650 AtomicMap[Walker->nr] = OtherWalker->nr;4651 }4652 }4653 *out << AtomicMap[Walker->nr] << "\t";4654 }4655 *out << endl;4656 }4657 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl;4658 return AtomicMap;4626 atom *Walker = NULL, *OtherWalker = NULL; 4627 *out << Verbose(3) << "Begin of GetFatherAtomicMap." << endl; 4628 int *AtomicMap = (int *) Malloc(sizeof(int)*AtomCount, "molecule::GetAtomicMap: *AtomicMap"); //Calloc 4629 for (int i=AtomCount;i--;) 4630 AtomicMap[i] = -1; 4631 if (OtherMolecule == this) { // same molecule 4632 for (int i=AtomCount;i--;) // no need as -1 means already that there is trivial correspondence 4633 AtomicMap[i] = i; 4634 *out << Verbose(4) << "Map is trivial." << endl; 4635 } else { 4636 *out << Verbose(4) << "Map is "; 4637 Walker = start; 4638 while (Walker->next != end) { 4639 Walker = Walker->next; 4640 if (Walker->father == NULL) { 4641 AtomicMap[Walker->nr] = -2; 4642 } else { 4643 OtherWalker = OtherMolecule->start; 4644 while (OtherWalker->next != OtherMolecule->end) { 4645 OtherWalker = OtherWalker->next; 4646 //for (int i=0;i<AtomCount;i++) { // search atom 4647 //for (int j=0;j<OtherMolecule->AtomCount;j++) { 4648 //*out << Verbose(4) << "Comparing father " << Walker->father << " with the other one " << OtherWalker->father << "." << endl; 4649 if (Walker->father == OtherWalker) 4650 AtomicMap[Walker->nr] = OtherWalker->nr; 4651 } 4652 } 4653 *out << AtomicMap[Walker->nr] << "\t"; 4654 } 4655 *out << endl; 4656 } 4657 *out << Verbose(3) << "End of GetFatherAtomicMap." << endl; 4658 return AtomicMap; 4659 4659 }; 4660 4660 … … 4670 4670 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4671 4671 { 4672 double temperature;4673 atom *Walker = NULL;4674 // test stream4675 if (output == NULL)4676 return false;4677 else4678 *output << "# Step Temperature [K] Temperature [a.u.]" << endl;4679 for (int step=startstep;step < endstep; step++) { // loop over all time steps4680 temperature = 0.;4681 Walker = start;4682 while (Walker->next != end) {4683 Walker = Walker->next;4684 for (int i=NDIM;i--;)4685 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i];4686 }4687 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl;4688 }4689 return true;4690 }; 4672 double temperature; 4673 atom *Walker = NULL; 4674 // test stream 4675 if (output == NULL) 4676 return false; 4677 else 4678 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4679 for (int step=startstep;step < endstep; step++) { // loop over all time steps 4680 temperature = 0.; 4681 Walker = start; 4682 while (Walker->next != end) { 4683 Walker = Walker->next; 4684 for (int i=NDIM;i--;) 4685 temperature += Walker->type->mass * Trajectories[Walker].U.at(step).x[i]* Trajectories[Walker].U.at(step).x[i]; 4686 } 4687 *output << step << "\t" << temperature*AtomicEnergyToKelvin << "\t" << temperature << endl; 4688 } 4689 return true; 4690 };
Note:
See TracChangeset
for help on using the changeset viewer.
