Changeset 69eb71 for src/molecules.cpp
- Timestamp:
- Dec 3, 2008, 2:12:05 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, 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:
- f683fe
- Parents:
- 1ffa21
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/molecules.cpp
r1ffa21 r69eb71 1 1 /** \file molecules.cpp 2 * 2 * 3 3 * Functions for the class molecule. 4 * 4 * 5 5 */ 6 6 … … 25 25 sum += (gsl_vector_get(x,j) - (vectors[i])->x[j])*(gsl_vector_get(x,j) - (vectors[i])->x[j]); 26 26 } 27 27 28 28 return sum; 29 29 }; … … 34 34 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 35 35 */ 36 molecule::molecule(periodentafel *teil) 37 { 36 molecule::molecule(periodentafel *teil) 37 { 38 38 // init atom chain list 39 start = new atom; 39 start = new atom; 40 40 end = new atom; 41 start->father = NULL; 41 start->father = NULL; 42 42 end->father = NULL; 43 43 link(start,end); … … 46 46 last = new bond(start, end, 1, -1); 47 47 link(first,last); 48 // other stuff 48 // other stuff 49 49 MDSteps = 0; 50 last_atom = 0; 50 last_atom = 0; 51 51 elemente = teil; 52 52 AtomCount = 0; … … 67 67 * Initialises molecule list with correctly referenced start and end, and sets molecule::last_atom to zero. 68 68 */ 69 molecule::~molecule() 69 molecule::~molecule() 70 70 { 71 71 if (ListOfBondsPerAtom != NULL) … … 78 78 delete(last); 79 79 delete(end); 80 delete(start); 80 delete(start); 81 81 }; 82 82 83 83 /** Adds given atom \a *pointer from molecule list. 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 84 * Increases molecule::last_atom and gives last number to added atom and names it according to its element::abbrev and molecule::AtomCount 85 85 * \param *pointer allocated and set atom 86 86 * \return true - succeeded, false - atom not found in list 87 87 */ 88 88 bool molecule::AddAtom(atom *pointer) 89 { 89 { 90 90 if (pointer != NULL) { 91 pointer->sort = &pointer->nr; 91 pointer->sort = &pointer->nr; 92 92 pointer->nr = last_atom++; // increase number within molecule 93 93 AtomCount++; … … 106 106 return add(pointer, end); 107 107 } else 108 return false; 108 return false; 109 109 }; 110 110 … … 115 115 */ 116 116 atom * molecule::AddCopyAtom(atom *pointer) 117 { 117 { 118 118 if (pointer != NULL) { 119 119 atom *walker = new atom(); … … 122 122 walker->v.CopyVector(&pointer->v); // copy velocity 123 123 walker->FixedIon = pointer->FixedIon; 124 walker->sort = &walker->nr; 124 walker->sort = &walker->nr; 125 125 walker->nr = last_atom++; // increase number within molecule 126 126 walker->father = pointer; //->GetTrueFather(); … … 133 133 return walker; 134 134 } else 135 return NULL; 135 return NULL; 136 136 }; 137 137 … … 156 156 * The lengths for these are \f$f\f$ and \f$g\f$ (from triangle H1-H2-(center of H1-H2-H3)) with knowledge that 157 157 * the median lines in an isosceles triangle meet in the center point with a ratio 2:1. 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 158 * \f[ f = \frac{b}{\sqrt{3}} \qquad g = \frac{b}{2} 159 159 * \f] 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 160 * as the coordination of all three atoms in the coordinate system of these three vectors: 161 161 * \f$\pmatrix{d & f & 0}\f$, \f$\pmatrix{d & -0.5 \cdot f & g}\f$ and \f$\pmatrix{d & -0.5 \cdot f & -g}\f$. 162 * 162 * 163 163 * \param *out output stream for debugging 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 164 * \param *Bond pointer to bond between \a *origin and \a *replacement 165 * \param *TopOrigin son of \a *origin of upper level molecule (the atom added to this molecule as a copy of \a *origin) 166 166 * \param *origin pointer to atom which acts as the origin for scaling the added hydrogen to correct bond length 167 167 * \param *replacement pointer to the atom which shall be copied as a hydrogen atom in this molecule … … 191 191 InBondvector.SubtractVector(&TopOrigin->x); 192 192 bondlength = InBondvector.Norm(); 193 193 194 194 // is greater than typical bond distance? Then we have to correct periodically 195 195 // the problem is not the H being out of the box, but InBondvector have the wrong direction 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 196 // due to TopReplacement or Origin being on the wrong side! 197 if (bondlength > BondDistance) { 198 198 // *out << Verbose(4) << "InBondvector is: "; 199 199 // InBondvector.Output(out); … … 215 215 // *out << endl; 216 216 } // periodic correction finished 217 217 218 218 InBondvector.Normalize(); 219 219 // get typical bond length and store as scale factor for later … … 222 222 cerr << Verbose(3) << "ERROR: There is no typical hydrogen bond distance in replacing bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") of degree " << TopBond->BondDegree << "!" << endl; 223 223 return false; 224 BondRescale = bondlength; 224 BondRescale = bondlength; 225 225 } else { 226 226 if (!IsAngstroem) … … 273 273 if (FirstOtherAtom != NULL) { // then we just have this double bond and the plane does not matter at all 274 274 // *out << Verbose(3) << "Regarding the double bond (" << TopOrigin->Name << "<->" << TopReplacement->Name << ") to be constructed: Taking " << FirstOtherAtom->Name << " and " << SecondOtherAtom->Name << " along with " << TopOrigin->Name << " to determine orthogonal plane." << endl; 275 275 276 276 // determine the plane of these two with the *origin 277 277 AllWentWell = AllWentWell && Orthovector1.MakeNormalVector(&TopOrigin->x, &FirstOtherAtom->x, &SecondOtherAtom->x); … … 286 286 Orthovector1.Normalize(); 287 287 //*out << Verbose(3) << "ReScaleCheck: " << Orthovector1.Norm() << " and " << InBondvector.Norm() << "." << endl; 288 288 289 289 // create the two Hydrogens ... 290 290 FirstOtherAtom = new atom(); … … 318 318 SecondOtherAtom->x.x[i] = InBondvector.x[i] * cos(bondangle) + Orthovector1.x[i] * (-sin(bondangle)); 319 319 } 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 320 FirstOtherAtom->x.Scale(&BondRescale); // rescale by correct BondDistance 321 321 SecondOtherAtom->x.Scale(&BondRescale); 322 322 //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl; 323 323 for(int i=NDIM;i--;) { // and make relative to origin atom 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 324 FirstOtherAtom->x.x[i] += TopOrigin->x.x[i]; 325 325 SecondOtherAtom->x.x[i] += TopOrigin->x.x[i]; 326 326 } … … 365 365 // *out << endl; 366 366 AllWentWell = AllWentWell && Orthovector2.MakeNormalVector(&InBondvector, &Orthovector1); 367 // *out << Verbose(3) << "Orthovector2: "; 367 // *out << Verbose(3) << "Orthovector2: "; 368 368 // Orthovector2.Output(out); 369 369 // *out << endl; 370 370 371 371 // create correct coordination for the three atoms 372 372 alpha = (TopOrigin->type->HBondAngle[2])/180.*M_PI/2.; // retrieve triple bond angle from database … … 380 380 factors[0] = d; 381 381 factors[1] = f; 382 factors[2] = 0.; 382 factors[2] = 0.; 383 383 FirstOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 384 384 factors[1] = -0.5*f; 385 factors[2] = g; 385 factors[2] = g; 386 386 SecondOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 387 factors[2] = -g; 387 factors[2] = -g; 388 388 ThirdOtherAtom->x.LinearCombinationOfVectors(&InBondvector, &Orthovector1, &Orthovector2, factors); 389 389 … … 437 437 */ 438 438 bool molecule::AddXYZFile(string filename) 439 { 439 { 440 440 istringstream *input = NULL; 441 441 int NumberOfAtoms = 0; // atom number in xyz read … … 446 446 string line; // currently parsed line 447 447 double x[3]; // atom coordinates 448 448 449 449 xyzfile.open(filename.c_str()); 450 450 if (!xyzfile) … … 454 454 input = new istringstream(line); 455 455 *input >> NumberOfAtoms; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 456 cout << Verbose(0) << "Parsing " << NumberOfAtoms << " atoms in file." << endl; 457 457 getline(xyzfile,line,'\n'); // Read comment 458 458 cout << Verbose(1) << "Comment: " << line << endl; 459 459 460 460 if (MDSteps == 0) // no atoms yet present 461 461 MDSteps++; … … 491 491 xyzfile.close(); 492 492 delete(input); 493 return true; 493 return true; 494 494 }; 495 495 … … 503 503 atom *LeftAtom = NULL, *RightAtom = NULL; 504 504 atom *Walker = NULL; 505 505 506 506 // copy all atoms 507 507 Walker = start; … … 510 510 CurrentAtom = copy->AddCopyAtom(Walker); 511 511 } 512 512 513 513 // copy all bonds 514 514 bond *Binder = first; … … 534 534 copy->NoCyclicBonds++; 535 535 NewBond->Type = Binder->Type; 536 } 536 } 537 537 // correct fathers 538 538 Walker = copy->start; … … 551 551 copy->CreateListOfBondsPerAtom((ofstream *)&cout); 552 552 } 553 553 554 554 return copy; 555 555 }; … … 576 576 577 577 /** Remove bond from bond chain list. 578 * \todo Function not implemented yet 578 * \todo Function not implemented yet 579 579 * \param *pointer bond pointer 580 580 * \return true - bound found and removed, false - bond not found/removed … … 588 588 589 589 /** Remove every bond from bond chain list that atom \a *BondPartner is a constituent of. 590 * \todo Function not implemented yet 590 * \todo Function not implemented yet 591 591 * \param *BondPartner atom to be removed 592 592 * \return true - bounds found and removed, false - bonds not found/removed … … 621 621 Vector *min = new Vector; 622 622 Vector *max = new Vector; 623 623 624 624 // gather min and max for each axis 625 625 ptr = start->next; // start at first in list … … 667 667 { 668 668 Vector *min = new Vector; 669 669 670 670 // *out << Verbose(3) << "Begin of CenterEdge." << endl; 671 671 atom *ptr = start->next; // start at first in list … … 683 683 } 684 684 } 685 // *out << Verbose(4) << "Maximum is "; 685 // *out << Verbose(4) << "Maximum is "; 686 686 // max->Output(out); 687 687 // *out << ", Minimum is "; … … 691 691 max->AddVector(min); 692 692 Translate(min); 693 } 693 } 694 694 delete(min); 695 695 // *out << Verbose(3) << "End of CenterEdge." << endl; 696 }; 696 }; 697 697 698 698 /** Centers the center of the atoms at (0,0,0). … … 704 704 int Num = 0; 705 705 atom *ptr = start->next; // start at first in list 706 706 707 707 for(int i=NDIM;i--;) // zero center vector 708 708 center->x[i] = 0.; 709 709 710 710 if (ptr != end) { //list not empty? 711 711 while (ptr->next != end) { // continue with second if present 712 712 ptr = ptr->next; 713 713 Num++; 714 center->AddVector(&ptr->x); 714 center->AddVector(&ptr->x); 715 715 } 716 716 center->Scale(-1./Num); // divide through total number (and sign for direction) 717 717 Translate(center); 718 718 } 719 }; 719 }; 720 720 721 721 /** Returns vector pointing to center of gravity. … … 729 729 Vector tmp; 730 730 double Num = 0; 731 731 732 732 a->Zero(); 733 733 … … 737 737 Num += 1.; 738 738 tmp.CopyVector(&ptr->x); 739 a->AddVector(&tmp); 739 a->AddVector(&tmp); 740 740 } 741 741 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 757 757 Vector tmp; 758 758 double Num = 0; 759 759 760 760 a->Zero(); 761 761 … … 766 766 tmp.CopyVector(&ptr->x); 767 767 tmp.Scale(ptr->type->mass); // scale by mass 768 a->AddVector(&tmp); 768 a->AddVector(&tmp); 769 769 } 770 770 a->Scale(-1./Num); // divide through total mass (and sign for direction) … … 789 789 Translate(center); 790 790 } 791 }; 791 }; 792 792 793 793 /** Scales all atoms by \a *factor. … … 803 803 Trajectories[ptr].R.at(j).Scale(factor); 804 804 ptr->x.Scale(factor); 805 } 806 }; 807 808 /** Translate all atoms by given vector. 805 } 806 }; 807 808 /** Translate all atoms by given vector. 809 809 * \param trans[] translation vector. 810 810 */ … … 818 818 Trajectories[ptr].R.at(j).Translate(trans); 819 819 ptr->x.Translate(trans); 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 820 } 821 }; 822 823 /** Mirrors all atoms against a given plane. 824 824 * \param n[] normal vector of mirror plane. 825 825 */ … … 833 833 Trajectories[ptr].R.at(j).Mirror(n); 834 834 ptr->x.Mirror(n); 835 } 835 } 836 836 }; 837 837 … … 847 847 bool flag; 848 848 Vector Testvector, Translationvector; 849 849 850 850 do { 851 851 Center.Zero(); … … 863 863 if (Walker->nr < Binder->GetOtherAtom(Walker)->nr) // otherwise we shift one to, the other fro and gain nothing 864 864 for (int j=0;j<NDIM;j++) { 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 865 tmp = Walker->x.x[j] - Binder->GetOtherAtom(Walker)->x.x[j]; 866 866 if ((fabs(tmp)) > BondDistance) { 867 867 flag = false; … … 879 879 cout << Verbose(1) << "vector is: "; 880 880 Testvector.Output((ofstream *)&cout); 881 cout << endl; 881 cout << endl; 882 882 #ifdef ADDHYDROGEN 883 883 // now also change all hydrogens … … 892 892 cout << Verbose(1) << "Hydrogen vector is: "; 893 893 Testvector.Output((ofstream *)&cout); 894 cout << endl; 894 cout << endl; 895 895 } 896 896 } … … 914 914 915 915 CenterGravity(out, CenterOfGravity); 916 917 // reset inertia tensor 916 917 // reset inertia tensor 918 918 for(int i=0;i<NDIM*NDIM;i++) 919 919 InertiaTensor[i] = 0.; 920 920 921 921 // sum up inertia tensor 922 922 while (ptr->next != end) { … … 943 943 } 944 944 *out << endl; 945 945 946 946 // diagonalize to determine principal axis system 947 947 gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM); … … 952 952 gsl_eigen_symmv_free(T); 953 953 gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC); 954 954 955 955 for(int i=0;i<NDIM;i++) { 956 956 *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i); 957 957 *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl; 958 958 } 959 959 960 960 // check whether we rotate or not 961 961 if (DoRotate) { 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 962 *out << Verbose(1) << "Transforming molecule into PAS ... "; 963 963 // the eigenvectors specify the transformation matrix 964 964 ptr = start; … … 972 972 973 973 // summing anew for debugging (resulting matrix has to be diagonal!) 974 // reset inertia tensor 974 // reset inertia tensor 975 975 for(int i=0;i<NDIM*NDIM;i++) 976 976 InertiaTensor[i] = 0.; 977 977 978 978 // sum up inertia tensor 979 979 ptr = start; … … 1002 1002 *out << endl; 1003 1003 } 1004 1004 1005 1005 // free everything 1006 1006 delete(CenterOfGravity); … … 1031 1031 1032 1032 CountElements(); // make sure ElementsInMolecule is up to date 1033 1033 1034 1034 // check file 1035 1035 if (input == NULL) { … … 1087 1087 Trajectories[walker].U.at(MDSteps).x[d] += 0.5*delta_t*(Trajectories[walker].F.at(MDSteps-1).x[d]+Trajectories[walker].F.at(MDSteps).x[d])/IonMass; 1088 1088 } 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1089 // cout << "Integrated position&velocity of step " << (MDSteps) << ": ("; 1090 1090 // for (int d=0;d<NDIM;d++) 1091 1091 // cout << Trajectories[walker].R.at(MDSteps).x[d] << " "; // next step … … 1121 1121 MDSteps++; 1122 1122 1123 1123 1124 1124 // exit 1125 1125 return true; 1126 1126 }; 1127 1127 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1128 /** Align all atoms in such a manner that given vector \a *n is along z axis. 1129 1129 * \param n[] alignment vector. 1130 1130 */ … … 1145 1145 ptr = ptr->next; 1146 1146 tmp = ptr->x.x[0]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1147 ptr->x.x[0] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1148 1148 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1149 1149 for (int j=0;j<MDSteps;j++) { 1150 1150 tmp = Trajectories[ptr].R.at(j).x[0]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1151 Trajectories[ptr].R.at(j).x[0] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1152 1152 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1153 1153 } 1154 } 1154 } 1155 1155 // rotate n vector 1156 1156 tmp = n->x[0]; … … 1160 1160 n->Output((ofstream *)&cout); 1161 1161 cout << endl; 1162 1162 1163 1163 // rotate on z-y plane 1164 1164 ptr = start; … … 1168 1168 ptr = ptr->next; 1169 1169 tmp = ptr->x.x[1]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1170 ptr->x.x[1] = cos(alpha) * tmp + sin(alpha) * ptr->x.x[2]; 1171 1171 ptr->x.x[2] = -sin(alpha) * tmp + cos(alpha) * ptr->x.x[2]; 1172 1172 for (int j=0;j<MDSteps;j++) { 1173 1173 tmp = Trajectories[ptr].R.at(j).x[1]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1174 Trajectories[ptr].R.at(j).x[1] = cos(alpha) * tmp + sin(alpha) * Trajectories[ptr].R.at(j).x[2]; 1175 1175 Trajectories[ptr].R.at(j).x[2] = -sin(alpha) * tmp + cos(alpha) * Trajectories[ptr].R.at(j).x[2]; 1176 1176 } 1177 } 1177 } 1178 1178 // rotate n vector (for consistency check) 1179 1179 tmp = n->x[1]; 1180 1180 n->x[1] = cos(alpha) * tmp + sin(alpha) * n->x[2]; 1181 1181 n->x[2] = -sin(alpha) * tmp + cos(alpha) * n->x[2]; 1182 1182 1183 1183 cout << Verbose(1) << "alignment vector after second rotation: "; 1184 1184 n->Output((ofstream *)&cout); … … 1191 1191 * \return true - succeeded, false - atom not found in list 1192 1192 */ 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1193 bool molecule::RemoveAtom(atom *pointer) 1194 { 1195 1195 if (ElementsInMolecule[pointer->type->Z] != 0) // this would indicate an error 1196 1196 ElementsInMolecule[pointer->type->Z]--; // decrease number of atom of this element 1197 1197 else 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1198 cerr << "ERROR: Atom " << pointer->Name << " is of element " << pointer->type->Z << " but the entry in the table of the molecule is 0!" << endl; 1199 1199 if (ElementsInMolecule[pointer->type->Z] == 0) // was last atom of this element? 1200 1200 ElementCount--; … … 1206 1206 * \return true - succeeded, false - atom not found in list 1207 1207 */ 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1208 bool molecule::CleanupMolecule() 1209 { 1210 return (cleanup(start,end) && cleanup(first,last)); 1211 1211 }; 1212 1212 … … 1222 1222 } else { 1223 1223 cout << Verbose(0) << "Atom not found in list." << endl; 1224 return NULL; 1224 return NULL; 1225 1225 } 1226 1226 }; … … 1271 1271 struct lsq_params *par = (struct lsq_params *)params; 1272 1272 atom *ptr = par->mol->start; 1273 1273 1274 1274 // initialize vectors 1275 1275 a.x[0] = gsl_vector_get(x,0); … … 1301 1301 { 1302 1302 int np = 6; 1303 1303 1304 1304 const gsl_multimin_fminimizer_type *T = 1305 1305 gsl_multimin_fminimizer_nmsimplex; … … 1307 1307 gsl_vector *ss; 1308 1308 gsl_multimin_function minex_func; 1309 1309 1310 1310 size_t iter = 0, i; 1311 1311 int status; 1312 1312 double size; 1313 1313 1314 1314 /* Initial vertex size vector */ 1315 1315 ss = gsl_vector_alloc (np); 1316 1316 1317 1317 /* Set all step sizes to 1 */ 1318 1318 gsl_vector_set_all (ss, 1.0); 1319 1319 1320 1320 /* Starting point */ 1321 1321 par->x = gsl_vector_alloc (np); 1322 1322 par->mol = this; 1323 1323 1324 1324 gsl_vector_set (par->x, 0, 0.0); // offset 1325 1325 gsl_vector_set (par->x, 1, 0.0); … … 1328 1328 gsl_vector_set (par->x, 4, 0.0); 1329 1329 gsl_vector_set (par->x, 5, 1.0); 1330 1330 1331 1331 /* Initialize method and iterate */ 1332 1332 minex_func.f = &LeastSquareDistance; 1333 1333 minex_func.n = np; 1334 1334 minex_func.params = (void *)par; 1335 1335 1336 1336 s = gsl_multimin_fminimizer_alloc (T, np); 1337 1337 gsl_multimin_fminimizer_set (s, &minex_func, par->x, ss); 1338 1338 1339 1339 do 1340 1340 { 1341 1341 iter++; 1342 1342 status = gsl_multimin_fminimizer_iterate(s); 1343 1343 1344 1344 if (status) 1345 1345 break; 1346 1346 1347 1347 size = gsl_multimin_fminimizer_size (s); 1348 1348 status = gsl_multimin_test_size (size, 1e-2); 1349 1349 1350 1350 if (status == GSL_SUCCESS) 1351 1351 { 1352 1352 printf ("converged to minimum at\n"); 1353 1353 } 1354 1354 1355 1355 printf ("%5d ", (int)iter); 1356 1356 for (i = 0; i < (size_t)np; i++) … … 1361 1361 } 1362 1362 while (status == GSL_CONTINUE && iter < 100); 1363 1363 1364 1364 for (i=0;i<(size_t)np;i++) 1365 1365 gsl_vector_set(par->x, i, gsl_vector_get(s->x, i)); … … 1378 1378 int ElementNo, AtomNo; 1379 1379 CountElements(); 1380 1380 1381 1381 if (out == NULL) { 1382 1382 return false; … … 1413 1413 int ElementNo, AtomNo; 1414 1414 CountElements(); 1415 1415 1416 1416 if (out == NULL) { 1417 1417 return false; … … 1460 1460 atom *Walker = start; 1461 1461 while (Walker->next != end) { 1462 Walker = Walker->next; 1462 Walker = Walker->next; 1463 1463 #ifdef ADDHYDROGEN 1464 1464 if (Walker->type->Z != 1) { // regard only non-hydrogen … … 1491 1491 int No = 0; 1492 1492 time_t now; 1493 1493 1494 1494 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1495 1495 walker = start; … … 1520 1520 int No = 0; 1521 1521 time_t now; 1522 1522 1523 1523 now = time((time_t *)NULL); // Get the system time and put it into 'now' as 'calender time' 1524 1524 walker = start; … … 1563 1563 Walker->nr = i; // update number in molecule (for easier referencing in FragmentMolecule lateron) 1564 1564 if (Walker->type->Z != 1) // count non-hydrogen atoms whilst at it 1565 NoNonHydrogen++; 1565 NoNonHydrogen++; 1566 1566 Free((void **)&Walker->Name, "molecule::CountAtoms: *walker->Name"); 1567 1567 Walker->Name = (char *) Malloc(sizeof(char)*6, "molecule::CountAtoms: *walker->Name"); … … 1571 1571 } 1572 1572 } else 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1573 *out << Verbose(3) << "AtomCount is still " << AtomCount << ", thus counting nothing." << endl; 1574 1574 } 1575 1575 }; … … 1583 1583 ElementsInMolecule[i] = 0; 1584 1584 ElementCount = 0; 1585 1585 1586 1586 atom *walker = start; 1587 1587 while (walker->next != end) { … … 1619 1619 Binder = Binder->next; 1620 1620 if (Binder->Cyclic) 1621 No++; 1621 No++; 1622 1622 } 1623 1623 delete(BackEdgeStack); … … 1679 1679 * Generally, we use the CSD approach to bond recognition, that is the the distance 1680 1680 * between two atoms A and B must be within [Rcov(A)+Rcov(B)-t,Rcov(A)+Rcov(B)+t] with 1681 * a threshold t = 0.4 Angstroem. 1681 * a threshold t = 0.4 Angstroem. 1682 1682 * To make it O(N log N) the function uses the linked-cell technique as follows: 1683 1683 * The procedure is step-wise: … … 1694 1694 * \param IsAngstroem whether coordinate system is gauged to Angstroem or Bohr radii 1695 1695 */ 1696 void molecule::CreateAdjacencyList2(ofstream *out, ifstream *input)// ofstream* out, double bonddistance, bool IsAngstroem) 1697 { 1698 1699 // 1 We will parse bonds out of the dbond file created by tremolo. 1700 int atom1, atom2, temp; 1701 atom *Walker, *OtherWalker; 1702 1703 if (!input) 1704 { 1705 cout << Verbose(1) << "Opening silica failed \n"; 1706 }; 1707 1708 *input >> ws >> atom1; 1709 *input >> ws >> atom2; 1710 cout << Verbose(1) << "Scanning file\n"; 1711 while (!input->eof()) // Check whether we read 2 items 1712 { 1713 *input >> ws >> atom1; 1714 *input >> ws >> atom2; 1715 if(atom2<atom1) //Sort indizes of atoms in order 1716 { 1717 temp=atom1; 1718 atom1=atom2; 1719 atom2=temp; 1720 }; 1721 1722 Walker=start; 1723 while(Walker-> nr != atom1) // Find atom corresponding to first index 1724 { 1725 Walker = Walker->next; 1726 }; 1727 OtherWalker = Walker->next; 1728 while(OtherWalker->nr != atom2) // Find atom corresponding to second index 1729 { 1730 OtherWalker= OtherWalker->next; 1731 }; 1732 AddBond(Walker, OtherWalker); //Add the bond between the two atoms with respective indices. 1733 BondCount++; //Increase bond count of molecule 1734 } 1735 1736 CreateListOfBondsPerAtom(out); 1737 1738 }; 1696 1739 void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem) 1697 1740 { 1741 1698 1742 atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL; 1699 1743 int No, NoBonds, CandidateBondNo; … … 1704 1748 Vector x; 1705 1749 int FalseBondDegree = 0; 1706 1750 1707 1751 BondDistance = bonddistance; // * ((IsAngstroem) ? 1. : 1./AtomicLengthToAngstroem); 1708 1752 *out << Verbose(0) << "Begin of CreateAdjacencyList." << endl; … … 1711 1755 cleanup(first,last); 1712 1756 } 1713 1757 1714 1758 // count atoms in molecule = dimension of matrix (also give each unique name and continuous numbering) 1715 1759 CountAtoms(out); … … 1730 1774 for (int i=NumberCells;i--;) 1731 1775 CellList[i] = NULL; 1732 1776 1733 1777 // 2b. put all atoms into its corresponding list 1734 1778 Walker = start; … … 1751 1795 if (CellList[index] == NULL) // allocate molecule if not done 1752 1796 CellList[index] = new molecule(elemente); 1753 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1754 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1797 OtherWalker = CellList[index]->AddCopyAtom(Walker); // add a copy of walker to this atom, father will be walker for later reference 1798 //*out << Verbose(1) << "Copy Atom is " << *OtherWalker << "." << endl; 1755 1799 } 1756 1800 //for (int i=0;i<NumberCells;i++) 1757 1801 //*out << Verbose(1) << "Cell number " << i << ": " << CellList[i] << "." << endl; 1758 1802 1803 1759 1804 // 3a. go through every cell 1760 1805 for (N[0]=divisor[0];N[0]--;) … … 1769 1814 Walker = Walker->next; 1770 1815 //*out << Verbose(0) << "Current Atom is " << *Walker << "." << endl; 1771 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1816 // 3c. check for possible bond between each atom in this and every one in the 27 cells 1772 1817 for (n[0]=-1;n[0]<=1;n[0]++) 1773 1818 for (n[1]=-1;n[1]<=1;n[1]++) … … 1801 1846 } 1802 1847 } 1848 1849 1850 1803 1851 // 4. free the cell again 1804 1852 for (int i=NumberCells;i--;) … … 1807 1855 } 1808 1856 Free((void **)&CellList, "molecule::CreateAdjacencyList - ** CellList"); 1809 1857 1810 1858 // create the adjacency list per atom 1811 1859 CreateListOfBondsPerAtom(out); 1812 1860 1813 1861 // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees, 1814 1862 // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene … … 1859 1907 *out << Verbose(1) << "BondCount is " << BondCount << ", no bonds between any of the " << AtomCount << " atoms." << endl; 1860 1908 *out << Verbose(1) << "I detected " << BondCount << " bonds in the molecule with distance " << bonddistance << ", " << FalseBondDegree << " bonds could not be corrected." << endl; 1861 1909 1862 1910 // output bonds for debugging (if bond chain list was correctly installed) 1863 1911 *out << Verbose(1) << endl << "From contents of bond chain list:"; … … 1869 1917 *out << endl; 1870 1918 } else 1871 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1919 *out << Verbose(1) << "AtomCount is " << AtomCount << ", thus no bonds, no connections!." << endl; 1872 1920 *out << Verbose(0) << "End of CreateAdjacencyList." << endl; 1873 1921 Free((void **)&matrix, "molecule::CreateAdjacencyList: *matrix"); 1874 }; 1922 1923 }; 1924 1925 1875 1926 1876 1927 /** Performs a Depth-First search on this molecule. … … 1893 1944 bond *Binder = NULL; 1894 1945 bool BackStepping = false; 1895 1946 1896 1947 *out << Verbose(0) << "Begin of DepthFirstSearchAnalysis" << endl; 1897 1948 1898 1949 ResetAllBondsToUnused(); 1899 1950 ResetAllAtomNumbers(); … … 1908 1959 LeafWalker->Leaf = new molecule(elemente); 1909 1960 LeafWalker->Leaf->AddCopyAtom(Root); 1910 1961 1911 1962 OldGraphNr = CurrentGraphNr; 1912 1963 Walker = Root; … … 1919 1970 AtomStack->Push(Walker); 1920 1971 CurrentGraphNr++; 1921 } 1972 } 1922 1973 do { // (3) if Walker has no unused egdes, go to (5) 1923 1974 BackStepping = false; // reset backstepping flag for (8) … … 1953 2004 Binder = NULL; 1954 2005 } while (1); // (2) 1955 2006 1956 2007 // if we came from backstepping, yet there were no more unused bonds, we end up here with no Ancestor, because Walker is Root! Then we are finished! 1957 2008 if ((Walker == Root) && (Binder == NULL)) 1958 2009 break; 1959 1960 // (5) if Ancestor of Walker is ... 2010 2011 // (5) if Ancestor of Walker is ... 1961 2012 *out << Verbose(1) << "(5) Number of Walker[" << Walker->Name << "]'s Ancestor[" << Walker->Ancestor->Name << "] is " << Walker->Ancestor->GraphNr << "." << endl; 1962 2013 if (Walker->Ancestor->GraphNr != Root->GraphNr) { … … 2001 2052 } while (OtherAtom != Walker); 2002 2053 ComponentNumber++; 2003 2054 2004 2055 // (11) Root is separation vertex, set Walker to Root and go to (4) 2005 2056 Walker = Root; … … 2014 2065 2015 2066 // From OldGraphNr to CurrentGraphNr ranges an disconnected subgraph 2016 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2067 *out << Verbose(0) << "Disconnected subgraph ranges from " << OldGraphNr << " to " << CurrentGraphNr << "." << endl; 2017 2068 LeafWalker->Leaf->Output(out); 2018 2069 *out << endl; … … 2022 2073 //*out << Verbose(1) << "Current next subgraph root candidate is " << Root->Name << "." << endl; 2023 2074 if (Root->GraphNr != -1) // if already discovered, step on 2024 Root = Root->next; 2075 Root = Root->next; 2025 2076 } 2026 2077 } … … 2044 2095 *out << " with Lowpoint " << Walker->LowpointNr << " and Graph Nr. " << Walker->GraphNr << "." << endl; 2045 2096 } 2046 2097 2047 2098 *out << Verbose(1) << "Final graph info for each bond is:" << endl; 2048 2099 Binder = first; … … 2055 2106 *out << ((Binder->rightatom->SeparationVertex) ? "SP," : "") << "L" << Binder->rightatom->LowpointNr << " G" << Binder->rightatom->GraphNr << " Comp."; 2056 2107 OutputComponentNumber(out, Binder->rightatom); 2057 *out << ">." << endl; 2108 *out << ">." << endl; 2058 2109 if (Binder->Cyclic) // cyclic ?? 2059 2110 *out << Verbose(3) << "Lowpoint at each side are equal: CYCLIC!" << endl; … … 2070 2121 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as 2071 2122 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds 2072 * as cyclic and print out the cycles. 2123 * as cyclic and print out the cycles. 2073 2124 * \param *out output stream for debugging 2074 2125 * \param *BackEdgeStack stack with all back edges found during DFS scan. Beware: This stack contains the bonds from the total molecule, not from the subgraph! … … 2081 2132 int *ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::CyclicStructureAnalysis: *ShortestPathList"); 2082 2133 enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList"); 2083 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2134 class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount); // will hold the current ring 2084 2135 class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount); // contains all "touched" atoms (that need to be reset after BFS loop) 2085 2136 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL; … … 2093 2144 ColorList[i] = white; 2094 2145 } 2095 2146 2096 2147 *out << Verbose(1) << "Back edge list - "; 2097 2148 BackEdgeStack->Output(out); 2098 2149 2099 2150 *out << Verbose(1) << "Analysing cycles ... " << endl; 2100 2151 NumCycles = 0; … … 2102 2153 BackEdge = BackEdgeStack->PopFirst(); 2103 2154 // this is the target 2104 Root = BackEdge->leftatom; 2155 Root = BackEdge->leftatom; 2105 2156 // this is the source point 2106 Walker = BackEdge->rightatom; 2157 Walker = BackEdge->rightatom; 2107 2158 ShortestPathList[Walker->nr] = 0; 2108 2159 BFSStack->ClearStack(); // start with empty BFS stack … … 2118 2169 if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder) 2119 2170 OtherAtom = Binder->GetOtherAtom(Walker); 2120 #ifdef ADDHYDROGEN 2171 #ifdef ADDHYDROGEN 2121 2172 if (OtherAtom->type->Z != 1) { 2122 2173 #endif … … 2127 2178 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 2128 2179 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2129 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2180 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 2130 2181 //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance 2131 2182 *out << Verbose(3) << "Putting OtherAtom into queue." << endl; … … 2137 2188 if (OtherAtom == Root) 2138 2189 break; 2139 #ifdef ADDHYDROGEN 2190 #ifdef ADDHYDROGEN 2140 2191 } else { 2141 2192 *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl; … … 2175 2226 } 2176 2227 } while ((!BFSStack->IsEmpty()) && (OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))); 2177 2228 2178 2229 if (OtherAtom == Root) { 2179 2230 // now climb back the predecessor list and thus find the cycle members … … 2203 2254 *out << Verbose(1) << "No ring containing " << *Root << " with length equal to or smaller than " << MinimumRingSize[Walker->GetTrueFather()->nr] << " found." << endl; 2204 2255 } 2205 2256 2206 2257 // now clean the lists 2207 2258 while (!TouchedStack->IsEmpty()){ … … 2213 2264 } 2214 2265 if (MinRingSize != -1) { 2215 // go over all atoms 2266 // go over all atoms 2216 2267 Root = start; 2217 2268 while(Root->next != end) { 2218 2269 Root = Root->next; 2219 2270 2220 2271 if (MinimumRingSize[Root->GetTrueFather()->nr] == AtomCount) { // check whether MinimumRingSize is set, if not BFS to next where it is 2221 2272 Walker = Root; … … 2254 2305 } 2255 2306 ColorList[Walker->nr] = black; 2256 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2307 //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 2257 2308 } 2258 2309 2259 2310 // now clean the lists 2260 2311 while (!TouchedStack->IsEmpty()){ … … 2305 2356 void molecule::OutputComponentNumber(ofstream *out, atom *vertex) 2306 2357 { 2307 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2358 for(int i=0;i<NumberOfBondsPerAtom[vertex->nr];i++) 2308 2359 *out << vertex->ComponentNr[i] << " "; 2309 2360 }; … … 2383 2434 { 2384 2435 int c = 0; 2385 int FragmentCount; 2436 int FragmentCount; 2386 2437 // get maximum bond degree 2387 2438 atom *Walker = start; … … 2393 2444 *out << Verbose(1) << "Upper limit for this subgraph is " << FragmentCount << " for " << NoNonHydrogen << " non-H atoms with maximum bond degree of " << c << "." << endl; 2394 2445 return FragmentCount; 2395 }; 2446 }; 2396 2447 2397 2448 /** Scans a single line for number and puts them into \a KeySet. 2398 2449 * \param *out output stream for debugging 2399 2450 * \param *buffer buffer to scan 2400 * \param &CurrentSet filled KeySet on return 2451 * \param &CurrentSet filled KeySet on return 2401 2452 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 2402 2453 */ … … 2406 2457 int AtomNr; 2407 2458 int status = 0; 2408 2459 2409 2460 line.str(buffer); 2410 2461 while (!line.eof()) { … … 2442 2493 double TEFactor; 2443 2494 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 2444 2495 2445 2496 if (FragmentList == NULL) { // check list pointer 2446 2497 FragmentList = new Graph; 2447 2498 } 2448 2499 2449 2500 // 1st pass: open file and read 2450 2501 *out << Verbose(1) << "Parsing the KeySet file ... " << endl; … … 2475 2526 status = false; 2476 2527 } 2477 2528 2478 2529 // 2nd pass: open TEFactors file and read 2479 2530 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 2487 2538 InputFile >> TEFactor; 2488 2539 (*runner).second.second = TEFactor; 2489 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2540 *out << Verbose(2) << "Setting " << ++NumberOfFragments << " fragment's TEFactor to " << (*runner).second.second << "." << endl; 2490 2541 } else { 2491 2542 status = false; … … 2528 2579 if(output != NULL) { 2529 2580 for(Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { 2530 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2581 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 2531 2582 if (sprinter != (*runner).first.begin()) 2532 2583 output << "\t"; … … 2594 2645 status = false; 2595 2646 } 2596 2647 2597 2648 return status; 2598 2649 }; … … 2603 2654 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 2604 2655 * \return true - structure is equal, false - not equivalence 2605 */ 2656 */ 2606 2657 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 2607 2658 { … … 2610 2661 bool status = true; 2611 2662 char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2612 2663 2613 2664 filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE; 2614 2665 File.open(filename.str().c_str(), ios::out); … … 2669 2720 *out << endl; 2670 2721 Free((void **)&buffer, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer"); 2671 2722 2672 2723 return status; 2673 2724 }; … … 2691 2742 for(int i=AtomCount;i--;) 2692 2743 AtomMask[i] = false; 2693 2744 2694 2745 if (Order < 0) { // adaptive increase of BondOrder per site 2695 2746 if (AtomMask[AtomCount] == true) // break after one step … … 2731 2782 line >> ws >> Value; // skip time entry 2732 2783 line >> ws >> Value; 2733 No -= 1; // indices start at 1 in file, not 0 2784 No -= 1; // indices start at 1 in file, not 0 2734 2785 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 2735 2786 … … 2740 2791 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 2741 2792 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 2742 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2793 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 2743 2794 if (!InsertedElement.second) { // this root is already present 2744 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2745 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 2795 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 2796 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 2746 2797 { // if value is smaller, update value and order 2747 2798 (*PresentItem).second.first = fabs(Value); … … 2781 2832 Walker = FindAtom(No); 2782 2833 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 2783 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2834 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 2784 2835 AtomMask[No] = true; 2785 2836 status = true; 2786 2837 //} else 2787 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 2838 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 2788 2839 } 2789 2840 // close and done … … 2819 2870 if ((Order == 0) && (AtomMask[AtomCount] == false)) // single stepping, just check 2820 2871 status = true; 2821 2872 2822 2873 if (!status) { 2823 2874 if (Order == 0) … … 2827 2878 } 2828 2879 } 2829 2880 2830 2881 // print atom mask for debugging 2831 2882 *out << " "; … … 2836 2887 *out << (AtomMask[i] ? "t" : "f"); 2837 2888 *out << endl; 2838 2889 2839 2890 return status; 2840 2891 }; … … 2850 2901 int AtomNo = 0; 2851 2902 atom *Walker = NULL; 2852 2903 2853 2904 if (SortIndex != NULL) { 2854 2905 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; … … 2908 2959 atom **ListOfAtoms = NULL; 2909 2960 atom ***ListOfLocalAtoms = NULL; 2910 bool *AtomMask = NULL; 2911 2961 bool *AtomMask = NULL; 2962 2912 2963 *out << endl; 2913 2964 #ifdef ADDHYDROGEN … … 2918 2969 2919 2970 // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++ 2920 2971 2921 2972 // ===== 1. Check whether bond structure is same as stored in files ==== 2922 2973 2923 2974 // fill the adjacency list 2924 2975 CreateListOfBondsPerAtom(out); … … 2926 2977 // create lookup table for Atom::nr 2927 2978 FragmentationToDo = FragmentationToDo && CreateFatherLookupTable(out, start, end, ListOfAtoms, AtomCount); 2928 2979 2929 2980 // === compare it with adjacency file === 2930 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2981 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2931 2982 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2932 2983 … … 2957 3008 delete(LocalBackEdgeStack); 2958 3009 } 2959 3010 2960 3011 // ===== 3. if structure still valid, parse key set file and others ===== 2961 3012 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList); … … 2963 3014 // ===== 4. check globally whether there's something to do actually (first adaptivity check) 2964 3015 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 2965 2966 // =================================== Begin of FRAGMENTATION =============================== 2967 // ===== 6a. assign each keyset to its respective subgraph ===== 3016 3017 // =================================== Begin of FRAGMENTATION =============================== 3018 // ===== 6a. assign each keyset to its respective subgraph ===== 2968 3019 Subgraphs->next->AssignKeySetsToFragment(out, this, ParsedFragmentList, ListOfLocalAtoms, FragmentList, (FragmentCounter = 0), true); 2969 3020 … … 2976 3027 FragmentationToDo = FragmentationToDo || CheckOrder; 2977 3028 AtomMask[AtomCount] = true; // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite() 2978 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 3029 // ===== 6b. fill RootStack for each subgraph (second adaptivity check) ===== 2979 3030 Subgraphs->next->FillRootStackForSubgraphs(out, RootStack, AtomMask, (FragmentCounter = 0)); 2980 3031 … … 3000 3051 delete(ParsedFragmentList); 3001 3052 delete[](MinimumRingSize); 3002 3053 3003 3054 3004 3055 // ==================================== End of FRAGMENTATION ============================================ … … 3006 3057 // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf) 3007 3058 Subgraphs->next->TranslateIndicesToGlobalIDs(out, FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph); 3008 3059 3009 3060 // free subgraph memory again 3010 3061 FragmentCounter = 0; … … 3031 3082 } 3032 3083 *out << k << "/" << BondFragments->NumberOfMolecules << " fragments generated from the keysets." << endl; 3033 3084 3034 3085 // ===== 9. Save fragments' configuration and keyset files et al to disk === 3035 3086 if (BondFragments->NumberOfMolecules != 0) { 3036 3087 // create the SortIndex from BFS labels to order in the config file 3037 3088 CreateMappingLabelsToConfigSequence(out, SortIndex); 3038 3089 3039 3090 *out << Verbose(1) << "Writing " << BondFragments->NumberOfMolecules << " possible bond fragmentation configs" << endl; 3040 3091 if (BondFragments->OutputConfigForListOfFragments(out, configuration, SortIndex)) … … 3042 3093 else 3043 3094 *out << Verbose(1) << "Some config writing failed." << endl; 3044 3095 3045 3096 // store force index reference file 3046 3097 BondFragments->StoreForcesFile(out, configuration->configpath, SortIndex); 3047 3048 // store keysets file 3098 3099 // store keysets file 3049 3100 StoreKeySetFile(out, TotalGraph, configuration->configpath); 3050 3051 // store Adjacency file 3101 3102 // store Adjacency file 3052 3103 StoreAdjacencyToFile(out, configuration->configpath); 3053 3104 3054 3105 // store Hydrogen saturation correction file 3055 3106 BondFragments->AddHydrogenCorrection(out, configuration->configpath); 3056 3107 3057 3108 // store adaptive orders into file 3058 3109 StoreOrderAtSiteFile(out, configuration->configpath); 3059 3110 3060 3111 // restore orbital and Stop values 3061 3112 CalculateOrbitals(*configuration); 3062 3113 3063 3114 // free memory for bond part 3064 3115 *out << Verbose(1) << "Freeing bond memory" << endl; 3065 3116 delete(FragmentList); // remove bond molecule from memory 3066 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3117 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 3067 3118 } else 3068 3119 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 3069 //} else 3120 //} else 3070 3121 // *out << Verbose(1) << "No fragments to store." << endl; 3071 3122 *out << Verbose(0) << "End of bond fragmentation." << endl; … … 3093 3144 atom *Walker = NULL, *OtherAtom = NULL; 3094 3145 ReferenceStack->Push(Binder); 3095 3146 3096 3147 do { // go through all bonds and push local ones 3097 3148 Walker = ListOfLocalAtoms[Binder->leftatom->nr]; // get one atom in the reference molecule 3098 if (Walker != NULL) // if this Walker exists in the subgraph ... 3149 if (Walker != NULL) // if this Walker exists in the subgraph ... 3099 3150 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through the local list of bonds 3100 3151 OtherAtom = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker); … … 3109 3160 ReferenceStack->Push(Binder); 3110 3161 } while (FirstBond != Binder); 3111 3162 3112 3163 return status; 3113 3164 }; … … 3185 3236 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 3186 3237 Walker->MaxOrder = MaxArray[Walker->nr]; 3187 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3238 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl; 3188 3239 } 3189 3240 file.close(); … … 3196 3247 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 3197 3248 Free((void **)&MaxArray, "molecule::ParseOrderAtSiteFromFile - *MaxArray"); 3198 3249 3199 3250 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 3200 3251 return status; … … 3254 3305 Walker = start; 3255 3306 while (Walker->next != end) { 3256 Walker = Walker->next; 3307 Walker = Walker->next; 3257 3308 *out << Verbose(4) << "Atom " << Walker->Name << "/" << Walker->nr << " with " << NumberOfBondsPerAtom[Walker->nr] << " bonds: "; 3258 3309 TotalDegree = 0; … … 3262 3313 } 3263 3314 *out << " -- TotalDegree: " << TotalDegree << endl; 3264 } 3315 } 3265 3316 *out << Verbose(1) << "End of Creating ListOfBondsPerAtom." << endl << endl; 3266 3317 }; … … 3268 3319 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 3269 3320 * Gray vertices are always enqueued in an StackClass<atom *> FIFO queue, the rest is usual BFS with adding vertices found was 3270 * white and putting into queue. 3321 * white and putting into queue. 3271 3322 * \param *out output stream for debugging 3272 3323 * \param *Mol Molecule class to add atoms to … … 3277 3328 * \param BondOrder maximum distance for vertices to add 3278 3329 * \param IsAngstroem lengths are in angstroem or bohrradii 3279 */ 3330 */ 3280 3331 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 3281 3332 { … … 3303 3354 } 3304 3355 ShortestPathList[Root->nr] = 0; 3305 3356 3306 3357 // and go on ... Queue always contains all lightgray vertices 3307 3358 while (!AtomStack->IsEmpty()) { … … 3311 3362 // followed by n+1 till top of stack. 3312 3363 Walker = AtomStack->PopFirst(); // pop oldest added 3313 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3364 *out << Verbose(1) << "Current Walker is: " << Walker->Name << ", and has " << NumberOfBondsPerAtom[Walker->nr] << " bonds." << endl; 3314 3365 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { 3315 3366 Binder = ListOfBondsPerAtom[Walker->nr][i]; … … 3318 3369 *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl; 3319 3370 if (ColorList[OtherAtom->nr] == white) { 3320 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3371 if (Binder != Bond) // let other atom white if it's via Root bond. In case it's cyclic it has to be reached again (yet Root is from OtherAtom already black, thus no problem) 3321 3372 ColorList[OtherAtom->nr] = lightgray; 3322 3373 PredecessorList[OtherAtom->nr] = Walker; // Walker is the predecessor 3323 3374 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 3324 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3375 *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " " << ((ColorList[OtherAtom->nr] == white) ? "white" : "lightgray") << ", its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl; 3325 3376 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 3326 3377 *out << Verbose(3); … … 3370 3421 // This has to be a cyclic bond, check whether it's present ... 3371 3422 if (AddedBondList[Binder->nr] == NULL) { 3372 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3423 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 3373 3424 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 3374 3425 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3385 3436 } 3386 3437 ColorList[Walker->nr] = black; 3387 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3438 *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl; 3388 3439 } 3389 3440 Free((void **)&PredecessorList, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 3409 3460 3410 3461 *out << Verbose(2) << "Begin of BuildInducedSubgraph." << endl; 3411 3462 3412 3463 // reset parent list 3413 3464 *out << Verbose(3) << "Resetting ParentList." << endl; 3414 3465 for (int i=Father->AtomCount;i--;) 3415 3466 ParentList[i] = NULL; 3416 3467 3417 3468 // fill parent list with sons 3418 3469 *out << Verbose(3) << "Filling Parent List." << endl; … … 3455 3506 * \param *&Leaf KeySet to look through 3456 3507 * \param *&ShortestPathList list of the shortest path to decide which atom to suggest as removal candidate in the end 3457 * \param index of the atom suggested for removal 3508 * \param index of the atom suggested for removal 3458 3509 */ 3459 3510 int molecule::LookForRemovalCandidate(ofstream *&out, KeySet *&Leaf, int *&ShortestPathList) … … 3461 3512 atom *Runner = NULL; 3462 3513 int SP, Removal; 3463 3514 3464 3515 *out << Verbose(2) << "Looking for removal candidate." << endl; 3465 3516 SP = -1; //0; // not -1, so that Root is never removed … … 3479 3530 /** Stores a fragment from \a KeySet into \a molecule. 3480 3531 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 3481 * molecule and adds missing hydrogen where bonds were cut. 3532 * molecule and adds missing hydrogen where bonds were cut. 3482 3533 * \param *out output stream for debugging messages 3483 * \param &Leaflet pointer to KeySet structure 3534 * \param &Leaflet pointer to KeySet structure 3484 3535 * \param IsAngstroem whether we have Ansgtroem or bohrradius 3485 3536 * \return pointer to constructed molecule … … 3492 3543 bool LonelyFlag = false; 3493 3544 int size; 3494 3545 3495 3546 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 3496 3547 3497 3548 Leaf->BondDistance = BondDistance; 3498 3549 for(int i=NDIM*2;i--;) 3499 Leaf->cell_size[i] = cell_size[i]; 3550 Leaf->cell_size[i] = cell_size[i]; 3500 3551 3501 3552 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) … … 3510 3561 size++; 3511 3562 } 3512 3563 3513 3564 // create the bonds between all: Make it an induced subgraph and add hydrogen 3514 3565 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; … … 3520 3571 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 3521 3572 // create all bonds 3522 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3573 for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 3523 3574 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 3524 3575 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 3525 3576 if (SonList[OtherFather->nr] != NULL) { 3526 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3577 // *out << ", whose son is " << *SonList[OtherFather->nr] << "." << endl; 3527 3578 if (OtherFather->nr > FatherOfRunner->nr) { // add bond (nr check is for adding only one of both variants: ab, ba) 3528 3579 // *out << Verbose(3) << "Adding Bond: "; 3529 // *out << 3580 // *out << 3530 3581 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 3531 3582 // *out << "." << endl; 3532 3583 //NumBonds[Runner->nr]++; 3533 } else { 3584 } else { 3534 3585 // *out << Verbose(3) << "Not adding bond, labels in wrong order." << endl; 3535 3586 } 3536 3587 LonelyFlag = false; 3537 3588 } else { 3538 // *out << ", who has no son in this fragment molecule." << endl; 3589 // *out << ", who has no son in this fragment molecule." << endl; 3539 3590 #ifdef ADDHYDROGEN 3540 3591 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; … … 3554 3605 while ((Runner->next != Leaf->end) && (Runner->next->type->Z == 1)) // skip added hydrogen 3555 3606 Runner = Runner->next; 3556 #endif 3607 #endif 3557 3608 } 3558 3609 Leaf->CreateListOfBondsPerAtom(out); … … 3587 3638 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself 3588 3639 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack! 3589 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3640 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL; 3590 3641 MoleculeListClass *FragmentList = NULL; 3591 3642 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL; … … 3637 3688 // clear snake stack 3638 3689 SnakeStack->ClearStack(); 3639 //SnakeStack->TestImplementation(out, start->next); 3690 //SnakeStack->TestImplementation(out, start->next); 3640 3691 3641 3692 ///// INNER LOOP //////////// … … 3658 3709 } 3659 3710 if (ShortestPathList[Walker->nr] == -1) { 3660 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3711 ShortestPathList[Walker->nr] = ShortestPathList[PredecessorList[Walker->nr]->nr]+1; 3661 3712 TouchedStack->Push(Walker); // mark every atom for lists cleanup later, whose shortest path has been changed 3662 3713 } … … 3696 3747 OtherAtom = Binder->GetOtherAtom(Walker); 3697 3748 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us 3698 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3749 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl; 3699 3750 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored 3700 3751 } else { // otherwise check its colour and element 3701 3752 if ( 3702 3753 #ifdef ADDHYDROGEN 3703 (OtherAtom->type->Z != 1) && 3754 (OtherAtom->type->Z != 1) && 3704 3755 #endif 3705 3756 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices … … 3711 3762 //} else { 3712 3763 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl; 3713 //} 3764 //} 3714 3765 Walker = OtherAtom; 3715 3766 break; 3716 3767 } else { 3717 if (OtherAtom->type->Z == 1) 3768 if (OtherAtom->type->Z == 1) 3718 3769 *out << "Links to a hydrogen atom." << endl; 3719 else 3770 else 3720 3771 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl; 3721 3772 } … … 3727 3778 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl; 3728 3779 } 3729 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3780 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black 3730 3781 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl; 3731 3782 ColorVertexList[Walker->nr] = black; … … 3734 3785 } 3735 3786 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black)); 3736 *out << Verbose(2) << "Inner Looping is finished." << endl; 3787 *out << Verbose(2) << "Inner Looping is finished." << endl; 3737 3788 3738 3789 // if we reset all AtomCount atoms, we have again technically O(N^2) ... … … 3750 3801 } 3751 3802 } 3752 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3803 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl; 3753 3804 3754 3805 // copy together 3755 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3806 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl; 3756 3807 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount); 3757 3808 RunningIndex = 0; … … 3824 3875 3825 3876 NumCombinations = 1 << SetDimension; 3826 3877 3827 3878 // Hier muessen von 1 bis NumberOfBondsPerAtom[Walker->nr] alle Kombinationen 3828 3879 // von Endstuecken (aus den Bonds) hinzugefᅵᅵgt werden und fᅵᅵr verbleibende ANOVAOrder 3829 3880 // rekursiv GraphCrawler in der nᅵᅵchsten Ebene aufgerufen werden 3830 3881 3831 3882 *out << Verbose(1+verbosity) << "Begin of SPFragmentGenerator." << endl; 3832 3883 *out << Verbose(1+verbosity) << "We are " << RootDistance << " away from Root, which is " << *FragmentSearch->Root << ", SubOrder is " << SubOrder << ", SetDimension is " << SetDimension << " and this means " << NumCombinations-1 << " combination(s)." << endl; 3833 3884 3834 // initialised touched list (stores added atoms on this level) 3885 // initialised touched list (stores added atoms on this level) 3835 3886 *out << Verbose(1+verbosity) << "Clearing touched list." << endl; 3836 3887 for (TouchedIndex=SubOrder+1;TouchedIndex--;) // empty touched list 3837 3888 TouchedList[TouchedIndex] = -1; 3838 3889 TouchedIndex = 0; 3839 3890 3840 3891 // create every possible combination of the endpieces 3841 3892 *out << Verbose(1+verbosity) << "Going through all combinations of the power set." << endl; … … 3845 3896 for (int j=SetDimension;j--;) 3846 3897 bits += (i & (1 << j)) >> j; 3847 3898 3848 3899 *out << Verbose(1+verbosity) << "Current set is " << Binary(i | (1 << SetDimension)) << ", number of bits is " << bits << "." << endl; 3849 3900 if (bits <= SubOrder) { // if not greater than additional atoms allowed on stack, continue … … 3853 3904 bit = ((i & (1 << j)) != 0); // mask the bit for the j-th bond 3854 3905 if (bit) { // if bit is set, we add this bond partner 3855 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3906 OtherWalker = BondsSet[j]->rightatom; // rightatom is always the one more distant, i.e. the one to add 3856 3907 //*out << Verbose(1+verbosity) << "Current Bond is " << ListOfBondsPerAtom[Walker->nr][i] << ", checking on " << *OtherWalker << "." << endl; 3857 3908 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3858 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3909 TestKeySetInsert = FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3859 3910 if (TestKeySetInsert.second) { 3860 3911 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added … … 3869 3920 } 3870 3921 } 3871 3872 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3922 3923 SpaceLeft = SubOrder - Added ;// SubOrder - bits; // due to item's maybe being already present, this does not work anymore 3873 3924 if (SpaceLeft > 0) { 3874 3925 *out << Verbose(1+verbosity) << "There's still some space left on stack: " << SpaceLeft << "." << endl; … … 3898 3949 } 3899 3950 *out << Verbose(2+verbosity) << "Calling subset generator " << SP << " away from root " << *FragmentSearch->Root << " with sub set dimension " << SubSetDimension << "." << endl; 3900 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3951 SPFragmentGenerator(out, FragmentSearch, SP, BondsList, SubSetDimension, SubOrder-bits); 3901 3952 Free((void **)&BondsList, "molecule::SPFragmentGenerator: **BondsList"); 3902 3953 } … … 3907 3958 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3908 3959 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3909 *out << (*runner) << " "; 3960 *out << (*runner) << " "; 3910 3961 *out << endl; 3911 3962 //if (!CheckForConnectedSubgraph(out, FragmentSearch->FragmentSet)) … … 3915 3966 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3916 3967 } 3917 3968 3918 3969 // --3-- remove all added items in this level from snake stack 3919 3970 *out << Verbose(1+verbosity) << "Removing all items that were added on this SP level " << RootDistance << "." << endl; … … 3926 3977 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3927 3978 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3928 *out << (*runner) << " "; 3979 *out << (*runner) << " "; 3929 3980 *out << endl; 3930 3981 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level … … 3933 3984 } 3934 3985 } 3935 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3986 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3936 3987 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3937 3988 }; … … 3942 3993 * \return true - connected, false - disconnected 3943 3994 * \note this is O(n^2) for it's just a bug checker not meant for permanent use! 3944 */ 3995 */ 3945 3996 bool molecule::CheckForConnectedSubgraph(ofstream *out, KeySet *Fragment) 3946 3997 { … … 3948 3999 bool BondStatus = false; 3949 4000 int size; 3950 4001 3951 4002 *out << Verbose(1) << "Begin of CheckForConnectedSubgraph" << endl; 3952 4003 *out << Verbose(2) << "Disconnected atom: "; 3953 4004 3954 4005 // count number of atoms in graph 3955 4006 size = 0; … … 3997 4048 * \param *out output stream for debugging 3998 4049 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 3999 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4050 * \param FragmentSearch UniqueFragments structure containing TEFactor, root atom and so on 4000 4051 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 4001 4052 * \return number of inserted fragments 4002 4053 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 4003 4054 */ 4004 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4055 int molecule::PowerSetGenerator(ofstream *out, int Order, struct UniqueFragments &FragmentSearch, KeySet RestrictedKeySet) 4005 4056 { 4006 4057 int SP, AtomKeyNr; … … 4023 4074 FragmentSearch.BondsPerSPCount[i] = 0; 4024 4075 FragmentSearch.BondsPerSPCount[0] = 1; 4025 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4076 Binder = new bond(FragmentSearch.Root, FragmentSearch.Root); 4026 4077 add(Binder, FragmentSearch.BondsPerSPList[1]); 4027 4078 4028 4079 // do a BFS search to fill the SP lists and label the found vertices 4029 4080 // Actually, we should construct a spanning tree vom the root atom and select all edges therefrom and put them into 4030 4081 // according shortest path lists. However, we don't. Rather we fill these lists right away, as they do form a spanning 4031 4082 // tree already sorted into various SP levels. That's why we just do loops over the depth (CurrentSP) and breadth 4032 // (EdgeinSPLevel) of this tree ... 4083 // (EdgeinSPLevel) of this tree ... 4033 4084 // In another picture, the bonds always contain a direction by rightatom being the one more distant from root and hence 4034 4085 // naturally leftatom forming its predecessor, preventing the BFS"seeker" from continuing in the wrong direction. … … 4083 4134 } 4084 4135 } 4085 4136 4086 4137 // outputting all list for debugging 4087 4138 *out << Verbose(0) << "Printing all found lists." << endl; … … 4092 4143 Binder = Binder->next; 4093 4144 *out << Verbose(2) << *Binder << endl; 4094 } 4095 } 4096 4145 } 4146 } 4147 4097 4148 // creating fragments with the found edge sets (may be done in reverse order, faster) 4098 4149 SP = -1; // the Root <-> Root edge must be subtracted! … … 4101 4152 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 4102 4153 Binder = Binder->next; 4103 SP ++; 4154 SP ++; 4104 4155 } 4105 4156 } … … 4108 4159 // start with root (push on fragment stack) 4109 4160 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 4110 FragmentSearch.FragmentSet->clear(); 4161 FragmentSearch.FragmentSet->clear(); 4111 4162 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 4112 4163 // prepare the subset and call the generator 4113 4164 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 4114 4165 BondsList[0] = FragmentSearch.BondsPerSPList[0]->next; // on SP level 0 there's only the root bond 4115 4166 4116 4167 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order); 4117 4168 4118 4169 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 4119 4170 } else { … … 4124 4175 // remove root from stack 4125 4176 *out << Verbose(0) << "Removing root again from stack." << endl; 4126 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4177 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 4127 4178 4128 4179 // free'ing the bonds lists … … 4143 4194 } 4144 4195 4145 // return list 4196 // return list 4146 4197 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 4147 4198 return (FragmentSearch.FragmentCounter - Counter); … … 4174 4225 // remove bonds that are beyond bonddistance 4175 4226 for(int i=NDIM;i--;) 4176 Translationvector.x[i] = 0.; 4227 Translationvector.x[i] = 0.; 4177 4228 // scan all bonds 4178 4229 Binder = first; … … 4221 4272 } 4222 4273 } 4223 // re-add bond 4274 // re-add bond 4224 4275 link(Binder, OtherBinder); 4225 4276 } else { … … 4275 4326 IteratorB++; 4276 4327 } // end of while loop 4277 }// end of check in case of equal sizes 4328 }// end of check in case of equal sizes 4278 4329 } 4279 4330 return false; // if we reach this point, they are equal … … 4319 4370 * \param graph1 first (dest) graph 4320 4371 * \param graph2 second (source) graph 4321 * \param *counter keyset counter that gets increased 4372 * \param *counter keyset counter that gets increased 4322 4373 */ 4323 4374 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 4364 4415 int RootKeyNr, RootNr; 4365 4416 struct UniqueFragments FragmentSearch; 4366 4417 4367 4418 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; 4368 4419 … … 4387 4438 Walker = Walker->next; 4388 4439 CompleteMolecule.insert(Walker->GetTrueFather()->nr); 4389 } 4440 } 4390 4441 4391 4442 // this can easily be seen: if Order is 5, then the number of levels for each lower order is the total sum of the number of levels above, as … … 4401 4452 //if ((MinimumRingSize[Walker->GetTrueFather()->nr] != -1) && (Walker->GetTrueFather()->AdaptiveOrder+1 > MinimumRingSize[Walker->GetTrueFather()->nr])) { 4402 4453 // *out << Verbose(0) << "Bond order " << Walker->GetTrueFather()->AdaptiveOrder << " of Root " << *Walker << " greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 4403 //} else 4454 //} else 4404 4455 { 4405 4456 // increase adaptive order by one 4406 4457 Walker->GetTrueFather()->AdaptiveOrder++; 4407 4458 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 4408 4459 4409 4460 // initialise Order-dependent entries of UniqueFragments structure 4410 4461 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); … … 4413 4464 FragmentSearch.BondsPerSPList[2*i] = new bond(); // start node 4414 4465 FragmentSearch.BondsPerSPList[2*i+1] = new bond(); // end node 4415 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4466 FragmentSearch.BondsPerSPList[2*i]->next = FragmentSearch.BondsPerSPList[2*i+1]; // intertwine these two 4416 4467 FragmentSearch.BondsPerSPList[2*i+1]->previous = FragmentSearch.BondsPerSPList[2*i]; 4417 4468 FragmentSearch.BondsPerSPCount[i] = 0; 4418 } 4419 4469 } 4470 4420 4471 // allocate memory for all lower level orders in this 1D-array of ptrs 4421 4472 NumLevels = 1 << (Order-1); // (int)pow(2,Order); … … 4423 4474 for (int i=0;i<NumLevels;i++) 4424 4475 FragmentLowerOrdersList[RootNr][i] = NULL; 4425 4476 4426 4477 // create top order where nothing is reduced 4427 4478 *out << Verbose(0) << "==============================================================================================================" << endl; 4428 4479 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", " << (RootStack.size()-RootNr) << " Roots remaining." << endl; // , NumLevels is " << NumLevels << " 4429 4480 4430 4481 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 4431 4482 FragmentLowerOrdersList[RootNr][0] = new Graph; … … 4440 4491 // we don't have to dive into suborders! These keysets are all already created on lower orders! 4441 4492 // this was all ancient stuff, when we still depended on the TEFactors (and for those the suborders were needed) 4442 4493 4443 4494 // if ((NumLevels >> 1) > 0) { 4444 4495 // // create lower order fragments … … 4447 4498 // for (int source=0;source<(NumLevels >> 1);source++) { // 1-terms don't need any more splitting, that's why only half is gone through (shift again) 4448 4499 // // step down to next order at (virtual) boundary of powers of 2 in array 4449 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4500 // while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 4450 4501 // Order--; 4451 4502 // *out << Verbose(0) << "Current Order is: " << Order << "." << endl; … … 4454 4505 // *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 4455 4506 // *out << Verbose(0) << "Current SubOrder is: " << SubOrder << " with source " << source << " to destination " << dest << "." << endl; 4456 // 4507 // 4457 4508 // // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 4458 4509 // //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; … … 4485 4536 RootStack.push_back(RootKeyNr); // put back on stack 4486 4537 RootNr++; 4487 4538 4488 4539 // free Order-dependent entries of UniqueFragments structure for next loop cycle 4489 4540 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); … … 4491 4542 delete(FragmentSearch.BondsPerSPList[2*i]); 4492 4543 delete(FragmentSearch.BondsPerSPList[2*i+1]); 4493 } 4544 } 4494 4545 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 4495 4546 } … … 4502 4553 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 4503 4554 delete(FragmentSearch.FragmentSet); 4504 4505 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4555 4556 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 4506 4557 // 5433222211111111 4507 4558 // 43221111 … … 4523 4574 RootKeyNr = RootStack.front(); 4524 4575 RootStack.pop_front(); 4525 Walker = FindAtom(RootKeyNr); 4576 Walker = FindAtom(RootKeyNr); 4526 4577 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 4527 4578 for(int i=0;i<NumLevels;i++) { … … 4536 4587 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 4537 4588 Free((void **)&NumMoleculesOfOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 4538 4589 4539 4590 *out << Verbose(0) << "End of FragmentBOSSANOVA." << endl; 4540 4591 }; … … 4570 4621 atom *Walker = NULL; 4571 4622 bool result = true; // status of comparison 4572 4573 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4623 4624 *out << Verbose(3) << "Begin of IsEqualToWithinThreshold." << endl; 4574 4625 /// first count both their atoms and elements and update lists thereby ... 4575 4626 //*out << Verbose(0) << "Counting atoms, updating list" << endl; … … 4618 4669 if (CenterOfGravity.Distance(&OtherCenterOfGravity) > threshold) { 4619 4670 *out << Verbose(4) << "Centers of gravity don't match." << endl; 4620 result = false; 4621 } 4622 } 4623 4671 result = false; 4672 } 4673 } 4674 4624 4675 /// ... then make a list with the euclidian distance to this center for each atom of both molecules 4625 4676 if (result) { … … 4637 4688 OtherDistances[Walker->nr] = OtherCenterOfGravity.Distance(&Walker->x); 4638 4689 } 4639 4690 4640 4691 /// ... sort each list (using heapsort (o(N log N)) from GSL) 4641 4692 *out << Verbose(5) << "Sorting distances" << endl; … … 4648 4699 for(int i=AtomCount;i--;) 4649 4700 PermutationMap[PermMap[i]] = (int) OtherPermMap[i]; 4650 4701 4651 4702 /// ... and compare them step by step, whether the difference is individiually(!) below \a threshold for all 4652 4703 *out << Verbose(4) << "Comparing distances" << endl; … … 4659 4710 Free((void **)&PermMap, "molecule::IsEqualToWithinThreshold: *PermMap"); 4660 4711 Free((void **)&OtherPermMap, "molecule::IsEqualToWithinThreshold: *OtherPermMap"); 4661 4712 4662 4713 /// free memory 4663 4714 Free((void **)&Distances, "molecule::IsEqualToWithinThreshold: Distances"); … … 4667 4718 result = false; 4668 4719 } 4669 } 4720 } 4670 4721 /// return pointer to map if all distances were below \a threshold 4671 4722 *out << Verbose(3) << "End of IsEqualToWithinThreshold." << endl; … … 4676 4727 *out << Verbose(3) << "Result: Not equal." << endl; 4677 4728 return NULL; 4678 } 4729 } 4679 4730 }; 4680 4731 … … 4731 4782 * \param *output output stream of temperature file 4732 4783 * \return file written (true), failure on writing file (false) 4733 */ 4784 */ 4734 4785 bool molecule::OutputTemperatureFromTrajectories(ofstream *out, int startstep, int endstep, ofstream *output) 4735 4786 { … … 4739 4790 if (output == NULL) 4740 4791 return false; 4741 else 4792 else 4742 4793 *output << "# Step Temperature [K] Temperature [a.u.]" << endl; 4743 4794 for (int step=startstep;step < endstep; step++) { // loop over all time steps
Note:
See TracChangeset
for help on using the changeset viewer.