Changeset c75363 for molecuilder/src/molecules.cpp
- Timestamp:
- May 2, 2008, 1:25:48 PM (17 years ago)
- Children:
- 30fda2
- Parents:
- e936b3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
molecuilder/src/molecules.cpp
re936b3 rc75363 1898 1898 return false; 1899 1899 } 1900 cout << Verbose(1) << "Parsing the KeySet file ... " ;1900 cout << Verbose(1) << "Parsing the KeySet file ... " << endl; 1901 1901 // open file and read 1902 1902 sprintf(filename, "%s/%s%s", path, FRAGMENTPREFIX, KEYSETFILE); … … 1942 1942 * \return true - file written successfully, false - writing failed 1943 1943 */ 1944 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path , int bondorder)1944 bool molecule::StoreAdjacencyToFile(ofstream *out, char *path) 1945 1945 { 1946 1946 ofstream AdjacencyFile; … … 1953 1953 cout << Verbose(1) << "Saving adjacency list ... "; 1954 1954 if (AdjacencyFile != NULL) { 1955 AdjacencyFile << "Order\t" << bondorder << endl;1956 1955 Walker = start; 1957 1956 while(Walker->next != end) { … … 1977 1976 * \param *path path to file 1978 1977 * \param **ListOfAtoms allocated (molecule::AtomCount) and filled lookup table for ids (Atom::nr) to *Atom 1979 * \param bondorder check whether files matches desired bond order1980 1978 * \return true - structure is equal, false - not equivalence 1981 1979 */ 1982 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms , int bondorder)1980 bool molecule::CheckAdjacencyFileAgainstMolecule(ofstream *out, char *path, atom **ListOfAtoms) 1983 1981 { 1984 1982 char *filename = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule - filename"); … … 1995 1993 int CurrentBondsOfAtom; 1996 1994 1997 // determine order from file 1998 File.getline(filename, MAXSTRINGSIZE); 1999 if (bondorder != atoi(&filename[5])) { 2000 *out << "Bond order desired is " << bondorder << " and does not match one in file " << filename[6] << "." << endl; 2001 status = false; 2002 } else { 2003 // Parse the file line by line and count the bonds 2004 while (!File.eof()) { 2005 File.getline(filename, MAXSTRINGSIZE); 2006 stringstream line; 2007 line.str(filename); 2008 int AtomNr = -1; 2009 line >> AtomNr; 2010 CurrentBondsOfAtom = -1; // we count one too far due to line end 2011 // parse into structure 2012 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2013 while (!line.eof()) 2014 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2015 // compare against present bonds 2016 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2017 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2018 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2019 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2020 int j = 0; 2021 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2022 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2023 ListOfAtoms[AtomNr] = NULL; 2024 NonMatchNumber++; 2025 status = false; 2026 //out << "[" << id << "]\t"; 2027 } else { 2028 //out << id << "\t"; 2029 } 1995 // Parse the file line by line and count the bonds 1996 while (!File.eof()) { 1997 File.getline(filename, MAXSTRINGSIZE); 1998 stringstream line; 1999 line.str(filename); 2000 int AtomNr = -1; 2001 line >> AtomNr; 2002 CurrentBondsOfAtom = -1; // we count one too far due to line end 2003 // parse into structure 2004 if ((AtomNr >= 0) && (AtomNr < AtomCount)) { 2005 while (!line.eof()) 2006 line >> CurrentBonds[ ++CurrentBondsOfAtom ]; 2007 // compare against present bonds 2008 //cout << Verbose(2) << "Walker is " << *Walker << ", bond partners: "; 2009 if (CurrentBondsOfAtom == NumberOfBondsPerAtom[AtomNr]) { 2010 for(int i=0;i<NumberOfBondsPerAtom[AtomNr];i++) { 2011 int id = ListOfBondsPerAtom[AtomNr][i]->GetOtherAtom(ListOfAtoms[AtomNr])->nr; 2012 int j = 0; 2013 for (;(j<CurrentBondsOfAtom) && (CurrentBonds[j++] != id);); // check against all parsed bonds 2014 if (CurrentBonds[j-1] != id) { // no match ? Then mark in ListOfAtoms 2015 ListOfAtoms[AtomNr] = NULL; 2016 NonMatchNumber++; 2017 status = false; 2018 //out << "[" << id << "]\t"; 2019 } else { 2020 //out << id << "\t"; 2030 2021 } 2031 //out << endl;2032 } else {2033 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl;2034 status = false;2035 2022 } 2023 //out << endl; 2024 } else { 2025 *out << "Number of bonds for Atom " << *ListOfAtoms[AtomNr] << " does not match, parsed " << CurrentBondsOfAtom << " against " << NumberOfBondsPerAtom[AtomNr] << "." << endl; 2026 status = false; 2036 2027 } 2037 2028 } 2038 File.close();2039 File.clear();2040 if (status) { // if equal we parse the KeySetFile2041 *out << " done: Equal." << endl;2042 status = true;2043 } else2044 *out << " done: Not equal by " << NonMatchNumber << " atoms." << endl;2045 }2029 } 2030 File.close(); 2031 File.clear(); 2032 if (status) { // if equal we parse the KeySetFile 2033 *out << " done: Equal." << endl; 2034 status = true; 2035 } else 2036 *out << " done: Not equal by " << NonMatchNumber << " atoms." << endl; 2046 2037 Free((void **)&CurrentBonds, "molecule::CheckAdjacencyFileAgainstMolecule - **CurrentBonds"); 2047 2038 } else { … … 2057 2048 * Writes for each fragment a config file. 2058 2049 * \param *out output stream for debugging 2059 * \param BottomUpOrder up to how many neighbouring bonds a fragment contains in BondOrderScheme::BottumUp scheme 2060 * \param TopDownOrder up to how many neighbouring bonds a fragment contains in BondOrderScheme::TopDown scheme 2061 * \param Scheme which BondOrderScheme to use for the fragmentation 2050 * \param Order up to how many neighbouring bonds a fragment contains in BondOrderScheme::BottumUp scheme 2062 2051 * \param *configuration configuration for writing config files for each fragment 2063 * \param CutCyclic whether to add cut cyclic bond or to saturate 2064 */ 2065 void molecule::FragmentMolecule(ofstream *out, int BottomUpOrder, int TopDownOrder, enum BondOrderScheme Scheme, config *configuration, enum CutCyclicBond CutCyclic) 2052 */ 2053 void molecule::FragmentMolecule(ofstream *out, int Order, config *configuration) 2066 2054 { 2067 2055 MoleculeListClass **BondFragments = NULL; … … 2072 2060 int AtomNo; 2073 2061 int MinimumRingSize; 2074 int TotalFragmentCounter = 0;2075 int FragmentCounter = 0;2062 int TotalFragmentCounter; 2063 int FragmentCounter; 2076 2064 MoleculeLeafClass *MolecularWalker = NULL; 2077 2065 MoleculeLeafClass *Subgraphs = NULL; // list of subgraphs from DFS analysis 2078 2066 fstream File; 2079 bool status= true;2080 2081 cout << endl;2067 bool FragmentationToDo = true; 2068 2069 *out << endl; 2082 2070 #ifdef ADDHYDROGEN 2083 cout << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl;2071 *out << Verbose(0) << "I will treat hydrogen special and saturate dangling bonds with it." << endl; 2084 2072 #else 2085 cout << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl;2073 *out << Verbose(0) << "Hydrogen is treated just like the rest of the lot." << endl; 2086 2074 #endif 2087 2075 … … 2101 2089 if (Walker->next != end) { // everything went alright 2102 2090 *out << " range of nuclear ids exceeded [0, AtomCount)." << endl; 2103 status = false; 2104 } 2105 status = status && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms, BottomUpOrder); 2106 if (status) { // NULL entries in ListOfAtoms contain NonMatches 2107 status = status && ParseKeySetFile(out, configuration->configpath, ListOfAtoms, FragmentList, configuration->GetIsAngstroem()); 2108 } 2091 FragmentationToDo = false; 2092 } 2093 FragmentationToDo = FragmentationToDo && CheckAdjacencyFileAgainstMolecule(out, configuration->configpath, ListOfAtoms); 2094 if (FragmentationToDo) // NULL entries in ListOfAtoms contain NonMatches 2095 FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ListOfAtoms, FragmentList, configuration->GetIsAngstroem()); 2096 if (FragmentationToDo) // parse the adaptive order per atom/site/vertex 2097 FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(out, configuration->configpath); 2109 2098 Free((void **)&ListOfAtoms, "molecule::FragmentMolecule - **ListOfAtoms"); 2110 2099 2111 2100 // =================================== Begin of FRAGMENTATION =============================== 2112 if (!status) { 2113 // === store Adjacency file === 2114 StoreAdjacencyToFile(out, configuration->configpath, BottomUpOrder); 2115 2101 if (FragmentationToDo) { // if we parsed Adjacancy, check whether OrderAtSite is above Order everywhere 2102 Walker = start; 2103 while (Walker->next != end) { // create a lookup table (Atom::nr -> atom) used as a marker table lateron 2104 Walker = Walker->next; 2105 #ifdef ADDHYDROGEN 2106 if (Walker->type->Z != 1) // skip hydrogen 2107 #endif 2108 if (Walker->AdaptiveOrder < Order) 2109 FragmentationToDo = false; 2110 } 2111 } 2112 2113 if (!FragmentationToDo) { // if we have still do something, FragmentationToDo will be false 2116 2114 // === first perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs === 2117 Subgraphs = DepthFirstSearchAnalysis((ofstream *)& cout, false, MinimumRingSize);2115 Subgraphs = DepthFirstSearchAnalysis((ofstream *)&*out, false, MinimumRingSize); 2118 2116 MolecularWalker = Subgraphs; 2119 2117 // fill the bond structure of the individually stored subgraphs 2120 2118 while (MolecularWalker->next != NULL) { 2121 2119 MolecularWalker = MolecularWalker->next; 2122 cout << Verbose(1) << "Creating adjacency list for subgraph " << MolecularWalker << "." << endl;2123 MolecularWalker->Leaf->CreateAdjacencyList( (ofstream *)&cout, BondDistance);2124 MolecularWalker->Leaf->CreateListOfBondsPerAtom( (ofstream *)&cout);2120 *out << Verbose(1) << "Creating adjacency list for subgraph " << MolecularWalker << "." << endl; 2121 MolecularWalker->Leaf->CreateAdjacencyList(out, BondDistance); 2122 MolecularWalker->Leaf->CreateListOfBondsPerAtom(out); 2125 2123 } 2126 2124 2127 2125 // === fragment all subgraphs === 2128 if ((MinimumRingSize != -1) && ( (BottomUpOrder >= MinimumRingSize) || (TopDownOrder >= MinimumRingSize))) {2129 cout << Verbose(0) << "Bond order greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl;2126 if ((MinimumRingSize != -1) && (Order >= MinimumRingSize)) { 2127 *out << Verbose(0) << "Bond order greater than or equal to Minimum Ring size of " << MinimumRingSize << " found is not allowed." << endl; 2130 2128 } else { 2131 2129 FragmentCounter = 0; 2132 2130 MolecularWalker = Subgraphs; 2133 // count subgraphs 2131 // count subgraphs and allocate fragments 2134 2132 while (MolecularWalker->next != NULL) { 2135 2133 MolecularWalker = MolecularWalker->next; … … 2137 2135 } 2138 2136 BondFragments = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*FragmentCounter, "molecule::FragmentMolecule - **BondFragments"); 2137 2138 // create RootStack for each Subgraph 2139 // NOTE: (keep this extern of following while loop, as lateron we may here look for which site to add to which subgraph) 2140 KeyStack RootStack[FragmentCounter]; 2141 2142 FragmentCounter = 0; 2143 MolecularWalker = Subgraphs; 2144 // count subgraphs and allocate fragments 2145 while (MolecularWalker->next != NULL) { 2146 MolecularWalker = MolecularWalker->next; 2147 RootStack[FragmentCounter].clear(); 2148 // find first root candidates 2149 Walker = MolecularWalker->Leaf->start; 2150 while (Walker->next != MolecularWalker->Leaf->end) { // go through all (non-hydrogen) atoms 2151 Walker = Walker->next; 2152 #ifdef ADDHYDROGEN 2153 if (Walker->type->Z != 1) // skip hydrogen 2154 #endif 2155 if (Walker->GetTrueFather()->AdaptiveOrder < Order) // only if Order is still greater 2156 RootStack[FragmentCounter].push_front(Walker->nr); 2157 } 2158 FragmentCounter++; 2159 } 2160 2139 2161 // fill the bond fragment list 2140 2162 FragmentCounter = 0; 2163 TotalFragmentCounter = 0; 2141 2164 MolecularWalker = Subgraphs; 2142 2165 while (MolecularWalker->next != NULL) { 2143 2166 MolecularWalker = MolecularWalker->next; 2144 cout << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl;2167 *out << Verbose(1) << "Fragmenting subgraph " << MolecularWalker << "." << endl; 2145 2168 if (MolecularWalker->Leaf->first->next != MolecularWalker->Leaf->last) { 2146 2169 // output ListOfBondsPerAtom for debugging … … 2165 2188 *out << Verbose(0) << "Begin of bond fragmentation." << endl; 2166 2189 BondFragments[FragmentCounter] = NULL; 2167 if (Scheme == ANOVA) { 2168 Graph *FragmentList = MolecularWalker->Leaf->FragmentBOSSANOVA(out,BottomUpOrder,configuration); 2169 2170 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 2171 int TotalNumberOfMolecules = 0; 2172 for(Graph::iterator runner = FragmentList->begin(); runner != FragmentList->end(); runner++) 2173 TotalNumberOfMolecules++; 2174 BondFragments[FragmentCounter] = new MoleculeListClass(TotalNumberOfMolecules, AtomCount); 2175 int k=0; 2176 for(Graph::iterator runner = FragmentList->begin(); runner != FragmentList->end(); runner++) { 2177 KeySet test = (*runner).first; 2178 BondFragments[FragmentCounter]->ListOfMolecules[k] = StoreFragmentFromKeySet(out, test, configuration); 2179 BondFragments[FragmentCounter]->TEList[k] = ((*runner).second).second; 2180 k++; 2181 } 2182 } 2183 if ((Scheme == BottomUp) || (Scheme == Combined)) { // get overlapping subgraphs 2184 BondFragments[FragmentCounter] = FragmentList = MolecularWalker->Leaf->FragmentBottomUp(out, BottomUpOrder, configuration, CutCyclic); 2190 // call BOSSANOVA method 2191 Graph *FragmentList = MolecularWalker->Leaf->FragmentBOSSANOVA(out, RootStack[FragmentCounter]); 2192 2193 // allocate memory for the pointer array and transmorph graphs into full molecular fragments 2194 int TotalNumberOfMolecules = 0; 2195 for(Graph::iterator runner = FragmentList->begin(); runner != FragmentList->end(); runner++) 2196 TotalNumberOfMolecules++; 2197 BondFragments[FragmentCounter] = new MoleculeListClass(TotalNumberOfMolecules, AtomCount); 2198 int k=0; 2199 for(Graph::iterator runner = FragmentList->begin(); runner != FragmentList->end(); runner++) { 2200 KeySet test = (*runner).first; 2201 *out << "Fragment No." << (*runner).second.first << " was created " << (int)(*runner).second.second << " time(s)." << endl; 2202 BondFragments[FragmentCounter]->ListOfMolecules[k] = MolecularWalker->Leaf->StoreFragmentFromKeySet(out, test, configuration); 2203 k++; 2185 2204 } 2186 if (Scheme == TopDown) { // initialise top level with whole molecule 2187 *out << Verbose(2) << "Initial memory allocating and initialising for whole molecule." << endl; 2188 FragmentList = new MoleculeListClass(1, MolecularWalker->Leaf->AtomCount); 2189 FragmentList->ListOfMolecules[0] = MolecularWalker->Leaf->CopyMolecule(); 2190 FragmentList->TEList[0] = 1.; 2191 } 2192 if ((Scheme == Combined) || (Scheme == TopDown)) { 2193 *out << Verbose(1) << "Calling TopDown." << endl; 2194 BondFragments[FragmentCounter] = FragmentList->FragmentTopDown(out, TopDownOrder, BondDistance, configuration, CutCyclic); 2195 // remove this molecule from list again and free wrapper list 2196 delete(FragmentList); 2197 FragmentList = NULL; 2198 } 2205 *out << k << "/" << BondFragments[FragmentCounter]->NumberOfMolecules << " fragments generated from the keysets." << endl; 2199 2206 } else { 2200 cout << Verbose(0) << "Connection matrix has not yet been generated!" << endl;2207 *out << Verbose(0) << "Connection matrix has not yet been generated!" << endl; 2201 2208 } 2202 2209 TotalFragmentCounter += BondFragments[FragmentCounter]->NumberOfMolecules; … … 2212 2219 FragmentList->ListOfMolecules[TotalFragmentCounter] = BondFragments[i]->ListOfMolecules[j]; 2213 2220 BondFragments[i]->ListOfMolecules[j] = NULL; 2214 FragmentList->TEList[TotalFragmentCounter++] = BondFragments[i]->TEList[j];2221 TotalFragmentCounter++; 2215 2222 } 2216 2223 delete(BondFragments[i]); … … 2218 2225 Free((void **)&BondFragments, "molecule::FragmentMolecule - **BondFragments"); 2219 2226 } else 2220 cout << Verbose(0) << "Usingfragments reconstructed from the KeySetFile." << endl;2227 *out << Verbose(0) << "Nothing to do, using only fragments reconstructed from the KeySetFile." << endl; 2221 2228 // ==================================== End of FRAGMENTATION ================================ 2222 2229 … … 2241 2248 } 2242 2249 *out << Verbose(1) << "Writing " << FragmentList->NumberOfMolecules << " possible bond fragmentation configs" << endl; 2243 if (FragmentList->OutputConfigForListOfFragments( "BondFragment", configuration, SortIndex))2250 if (FragmentList->OutputConfigForListOfFragments(out, configuration, SortIndex)) 2244 2251 *out << Verbose(1) << "All configs written." << endl; 2245 2252 else 2246 2253 *out << Verbose(1) << "Some configs' writing failed." << endl; 2247 2254 Free((void **)&SortIndex, "molecule::FragmentMolecule: *SortIndex"); 2255 2256 // === store Adjacency file === 2257 StoreAdjacencyToFile(out, configuration->configpath); 2258 2259 // Store adaptive orders into file 2260 StoreOrderAtSiteFile(out, configuration->configpath); 2248 2261 2249 2262 // restore orbital and Stop values … … 2256 2269 } else 2257 2270 *out << Verbose(1) << "FragmentList is zero on return, splitting failed." << endl; 2271 2258 2272 // free subgraph memory again 2259 2273 if (Subgraphs != NULL) { … … 2266 2280 2267 2281 *out << Verbose(0) << "End of bond fragmentation." << endl; 2282 }; 2283 2284 /** Stores pairs (Atom::nr, Atom::AdaptiveOrder) into file. 2285 * Atoms not present in the file get "-1". 2286 * \param *out output stream for debugging 2287 * \param *path path to file ORDERATSITEFILE 2288 * \return true - file writable, false - not writable 2289 */ 2290 bool molecule::StoreOrderAtSiteFile(ofstream *out, char *path) 2291 { 2292 stringstream line; 2293 ofstream file; 2294 2295 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 2296 file.open(line.str().c_str()); 2297 *out << Verbose(0) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 2298 if (file != NULL) { 2299 atom *Walker = start; 2300 while (Walker->next != end) { 2301 Walker = Walker->next; 2302 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << endl; 2303 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "." << endl; 2304 } 2305 file.close(); 2306 return true; 2307 } else { 2308 return false; 2309 } 2310 }; 2311 2312 /** Parses pairs(Atom::nr, Atom::AdaptiveOrder) from file and stores in molecule's Atom's. 2313 * Atoms not present in the file get "0". 2314 * \param *out output stream for debugging 2315 * \param *path path to file ORDERATSITEFILEe 2316 * \return true - file found and scanned, false - file not found 2317 * \sa ParseKeySetFile() and CheckAdjacencyFileAgainstMolecule() as this is meant to be used in conjunction with the two 2318 */ 2319 bool molecule::ParseOrderAtSiteFromFile(ofstream *out, char *path) 2320 { 2321 unsigned char *OrderArray = (unsigned char *) Malloc(sizeof(unsigned char)*AtomCount, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 2322 bool status; 2323 int AtomNr; 2324 stringstream line; 2325 ifstream file; 2326 int Order; 2327 2328 *out << Verbose(1) << "Begin of ParseOrderAtSiteFromFile" << endl; 2329 for(int i=0;i<AtomCount;i++) 2330 OrderArray[i] = 0; 2331 line << path << "/" << FRAGMENTPREFIX << ORDERATSITEFILE; 2332 file.open(line.str().c_str()); 2333 if (file != NULL) { 2334 for (int i=0;i<AtomCount;i++) // initialise with 0 2335 OrderArray[i] = 0; 2336 while (!file.eof()) { // parse from file 2337 file >> AtomNr; 2338 file >> Order; 2339 OrderArray[AtomNr] = (unsigned char) Order; 2340 //*out << Verbose(2) << "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << "." << endl; 2341 } 2342 atom *Walker = start; 2343 while (Walker->next != end) { // fill into atom classes 2344 Walker = Walker->next; 2345 Walker->AdaptiveOrder = OrderArray[Walker->nr]; 2346 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << "." << endl; 2347 } 2348 file.close(); 2349 status = true; 2350 } else { 2351 status = false; 2352 } 2353 Free((void **)&OrderArray, "molecule::ParseOrderAtSiteFromFile - *OrderArray"); 2354 2355 *out << Verbose(1) << "End of ParseOrderAtSiteFromFile" << endl; 2356 return status; 2268 2357 }; 2269 2358 … … 2333 2422 }; 2334 2423 2335 /** Splits up a molecule into atomic, non-hydrogen, hydrogen-saturated fragments.2336 * \param *out output stream for debugging2337 * \param NumberOfTopAtoms number to initialise second parameter of MoleculeListClass with2338 * \param IsAngstroem whether atomic coordination is in Angstroem (true) or atomic length/bohrradous (false)2339 * \param factor additional factor TE and forces factors are multiplied with2340 * \param CutCyclic whether to add cut cyclic bond or to saturate2341 * \return MoleculelistClass of pointer to each atomic fragment.2342 */2343 MoleculeListClass * molecule::GetAtomicFragments(ofstream *out, int NumberOfTopAtoms, bool IsAngstroem, double factor, enum CutCyclicBond CutCyclic)2344 {2345 atom *TopAtom = NULL, *BottomAtom = NULL; // Top = this, Bottom = AtomicFragment->ListOfMolecules[No]2346 atom *Walker = NULL;2347 MoleculeListClass *AtomicFragments = NULL;2348 atom **AtomList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::GetAtomicFragments: **AtomList");2349 for (int i=0;i<AtomCount;i++)2350 AtomList[i] = NULL;2351 bond **BondList = (bond **) Malloc(sizeof(bond *)*BondCount, "molecule::GetAtomicFragments: **AtomList");2352 for (int i=0;i<BondCount;i++)2353 BondList[i] = NULL;2354 int No = 0, Cyclic;2355 2356 *out << Verbose(0) << "Begin of GetAtomicFragments." << endl;2357 2358 *out << Verbose(1) << "Atoms in Molecule: ";2359 Walker = start;2360 while (Walker->next != end) {2361 Walker = Walker->next;2362 *out << Walker << "\t";2363 }2364 *out << endl;2365 #ifdef ADDHYDROGEN2366 if (NoNonHydrogen != 0) {2367 AtomicFragments = new MoleculeListClass(NoNonHydrogen, NumberOfTopAtoms);2368 } else {2369 *out << Verbose(1) << "NoNonHydrogen is " << NoNonHydrogen << ", can't allocated MoleculeListClass." << endl;2370 #else2371 if (AtomCount != 0) {2372 AtomicFragments = new MoleculeListClass(AtomCount, NumberOfTopAtoms);2373 } else {2374 *out << Verbose(1) << "AtomCount is " << AtomCount << ", can't allocated MoleculeListClass." << endl;2375 #endif2376 return (AtomicFragments);2377 }2378 2379 TopAtom = start;2380 while (TopAtom->next != end) {2381 TopAtom = TopAtom->next;2382 //for(int i=0;i<AtomCount;i++) {2383 #ifdef ADDHYDROGEN2384 if (TopAtom->type->Z != 1) { // regard only non-hydrogen2385 #endif2386 //TopAtom = AtomsInMolecule[i];2387 *out << Verbose(1) << "Current non-Hydrogen Atom: " << TopAtom->Name << endl;2388 2389 // go through all bonds to check if cyclic2390 Cyclic = 0;2391 for(int i=0;i<NumberOfBondsPerAtom[TopAtom->nr];i++)2392 Cyclic += (ListOfBondsPerAtom[TopAtom->nr][i]->Cyclic) ? 1 : 0;2393 2394 #ifdef ADDHYDROGEN2395 if (No > NoNonHydrogen) {2396 #else2397 if (No > AtomCount) {2398 #endif2399 *out << Verbose(1) << "Access on created AtomicFragmentsListOfMolecules[" << No << "] beyond NumberOfMolecules " << AtomicFragments->NumberOfMolecules << "." << endl;2400 break;2401 }2402 if (AtomList[TopAtom->nr] == NULL) {2403 // create new molecule2404 AtomicFragments->ListOfMolecules[No] = new molecule(elemente); // allocate memory2405 AtomicFragments->TEList[No] = factor;2406 AtomicFragments->ListOfMolecules[No]->BondDistance = BondDistance;2407 2408 // add central atom2409 BottomAtom = AtomicFragments->ListOfMolecules[No]->AddCopyAtom(TopAtom); // add this central atom to molecule2410 AtomList[TopAtom->nr] = BottomAtom; // mark down in list2411 2412 // create fragment2413 *out << Verbose(1) << "New fragment around atom: " << TopAtom->Name << endl;2414 BreadthFirstSearchAdd(out,AtomicFragments->ListOfMolecules[No], AtomList, BondList, TopAtom, NULL, 0, IsAngstroem, (Cyclic == 0) ? SaturateBond : CutCyclic);2415 AtomicFragments->ListOfMolecules[No]->CountAtoms(out);2416 // actually we now have to reset both arrays to NULL again, but BFS is overkill anyway for getting the atomic fragments2417 // thus we do it in O(1) and avoid the O(n) which would make this routine O(N^2)!2418 AtomList[TopAtom->nr] = NULL; // remove this fragment's central atom again from the list2419 2420 *out << Verbose(1) << "Atoms in Fragment " << TopAtom->nr << ": ";2421 Walker = AtomicFragments->ListOfMolecules[No]->start;2422 while (Walker->next != AtomicFragments->ListOfMolecules[No]->end) {2423 Walker = Walker->next;2424 //for(int k=0;k<AtomicFragments->ListOfMolecules[No]->AtomCount;k++)2425 *out << Walker << "(" << Walker->father << ")\t";2426 }2427 *out << endl;2428 No++;2429 }2430 #ifdef ADDHYDROGEN2431 } else2432 *out << Verbose(1) << "Current Hydrogen Atom: " << TopAtom->Name << endl;2433 #endif2434 }2435 2436 // output of full list before reduction2437 if (AtomicFragments != NULL) {2438 *out << "AtomicFragments: ";2439 AtomicFragments->Output(out);2440 *out << endl;2441 } else2442 *out << Verbose(1) << "AtomicFragments is zero on return, splitting failed." << endl;2443 2444 // Reducing the atomic fragments2445 if (AtomicFragments != NULL) {2446 // check whether there are equal fragments by GetMappingToUniqueFragments2447 AtomicFragments->ReduceToUniqueList(out, &cell_size[0], BondDistance);2448 } else2449 *out << Verbose(1) << "AtomicFragments is zero, reducing failed." << endl;2450 Free((void **)&BondList, "molecule::GetAtomicFragments: **BondList");2451 Free((void **)&AtomList, "molecule::GetAtomicFragments: **AtomList");2452 *out << Verbose(0) << "End of GetAtomicFragments." << endl;2453 return (AtomicFragments);2454 };2455 2456 /** Splits up the bond in a molecule into a left and a right fragment.2457 * \param *out output stream for debugging2458 * \param *Bond bond to broken up into getting allocated ...2459 * \param *LeftFragment ... left fragment molecule ... (ptr to the memory cell wherein the adress for the Fragment is to be stored)2460 * \param *RightFragment ... and right fragment molecule to be returned.(ptr to the memory cell wherein the adress for the Fragment is to be stored)2461 * \param IsAngstroem whether atomic coordination is in Angstroem (true) or atomic length/bohrradous (false)2462 * \param CutCyclic whether to add cut cyclic bond or not2463 * \sa FragmentTopDown()2464 */2465 void molecule::FragmentMoleculeByBond(ofstream *out, bond *Bond, molecule **LeftFragment, molecule **RightFragment, bool IsAngstroem, enum CutCyclicBond CutCyclic)2466 {2467 *out << Verbose(0) << "Begin of FragmentMoleculeByBond." << endl;2468 #ifdef ADDHYDROGEN2469 if ((Bond->leftatom->type->Z != 1) && (Bond->rightatom->type->Z != 1)) { // if both bond partners aren't hydrogen ...2470 #endif2471 *out << Verbose(1) << "Current Non-Hydrogen Bond: " << Bond->leftatom->Name << " and " << Bond->rightatom->Name << endl;2472 *LeftFragment = new molecule(elemente);2473 *RightFragment = new molecule(elemente);2474 // initialise marker list for all atoms2475 atom **AddedAtomListLeft = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::FragmentMoleculeByBond: **AddedAtomListLeft");2476 atom **AddedAtomListRight = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::FragmentMoleculeByBond: **AddedAtomListRight");2477 for (int i=0;i<AtomCount;i++) {2478 AddedAtomListLeft[i] = NULL;2479 AddedAtomListRight[i] = NULL;2480 }2481 bond **AddedBondListLeft = (bond **) Malloc(sizeof(bond *)*BondCount, "molecule::FragmentMoleculeByBond: **AddedBondListLeft");2482 bond **AddedBondListRight = (bond **) Malloc(sizeof(bond *)*BondCount, "molecule::FragmentMoleculeByBond: **AddedBondListRight");2483 for (int i=0;i<BondCount;i++) {2484 AddedBondListLeft[i] = NULL;2485 AddedBondListRight[i] = NULL;2486 }2487 2488 // tag and add all atoms that have to be included2489 *out << Verbose(1) << "Adding BFS-wise on left hand side with Bond Order " << NoNonBonds-1 << "." << endl;2490 AddedAtomListLeft[Bond->leftatom->nr] = (*LeftFragment)->AddCopyAtom(Bond->leftatom);2491 BreadthFirstSearchAdd(out, *LeftFragment, AddedAtomListLeft, AddedBondListLeft, Bond->leftatom, Bond,2492 #ifdef ADDHYDROGEN2493 NoNonBonds2494 #else2495 BondCount2496 #endif2497 , IsAngstroem, CutCyclic);2498 *out << Verbose(1) << "Adding BFS-wise on right hand side with Bond Order " << NoNonBonds-1 << "." << endl;2499 AddedAtomListRight[Bond->rightatom->nr] = (*RightFragment)->AddCopyAtom(Bond->rightatom);2500 BreadthFirstSearchAdd(out, *RightFragment, AddedAtomListRight, AddedBondListRight, Bond->rightatom, Bond,2501 #ifdef ADDHYDROGEN2502 NoNonBonds2503 #else2504 BondCount2505 #endif2506 , IsAngstroem, CutCyclic);2507 2508 // count atoms2509 (*LeftFragment)->CountAtoms(out);2510 (*RightFragment)->CountAtoms(out);2511 // free all and exit2512 Free((void **)&AddedAtomListLeft, "molecule::FragmentMoleculeByBond: **AddedAtomListLeft");2513 Free((void **)&AddedAtomListRight, "molecule::FragmentMoleculeByBond: **AddedAtomListRight");2514 Free((void **)&AddedBondListLeft, "molecule::FragmentMoleculeByBond: **AddedBondListLeft");2515 Free((void **)&AddedBondListRight, "molecule::FragmentMoleculeByBond: **AddedBondListRight");2516 #ifdef ADDHYDROGEN2517 }2518 #endif2519 *out << Verbose(0) << "End of FragmentMoleculeByBond." << endl;2520 };2521 2522 /** Returns the given \a **FragmentList filled with molecules around each bond including up to \a BondDegree neighbours.2523 * \param *out output stream for debugging2524 * \param BondOrder neighbours on each side to be ...2525 * \param IsAngstroem whether atomic coordination is in Angstroem (true) or atomic length/bohrradous (false)2526 * \param CutCyclic whether to add cut cyclic bond or to saturate2527 * \sa FragmentBottomUp(), molecule::AddBondOrdertoMolecule()2528 */2529 MoleculeListClass * molecule::GetEachBondFragmentOfOrder(ofstream *out, int BondOrder, bool IsAngstroem, enum CutCyclicBond CutCyclic)2530 {2531 /// Allocate memory for Bond list and go through each bond and fragment molecule up to bond order and fill the list to be returned.2532 MoleculeListClass *FragmentList = NULL;2533 atom **AddedAtomList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::GetBondFragmentOfOrder: **AddedAtomList");2534 bond **AddedBondList = (bond **) Malloc(sizeof(bond *)*BondCount, "molecule::GetBondFragmentOfOrder: **AddedBondList");2535 bond *Binder = NULL;2536 2537 *out << Verbose(0) << "Begin of GetEachBondFragmentOfOrder." << endl;2538 #ifdef ADDHYDROGEN2539 if (NoNonBonds != 0) {2540 FragmentList = new MoleculeListClass(NoNonBonds, AtomCount);2541 } else {2542 *out << Verbose(1) << "NoNonBonds is " << NoNonBonds << ", can't allocate list." << endl;2543 #else2544 if (BondCount != 0) {2545 FragmentList = new MoleculeListClass(BondCount, AtomCount);2546 } else {2547 *out << Verbose(1) << "BondCount is " << BondCount << ", can't allocate list." << endl;2548 #endif2549 }2550 int No = 0;2551 Binder = first;2552 while (Binder->next != last) { // get each bond, NULL is returned if it is a H-H bond2553 Binder = Binder->next;2554 #ifdef ADDHYDROGEN2555 if ((Binder->leftatom->type->Z != 1) && (Binder->rightatom->type->Z != 1)) // if both bond partners aren't hydrogen ...2556 #endif2557 if ((CutCyclic == SaturateBond) || (!Binder->Cyclic)) {2558 *out << Verbose(1) << "Getting Fragment for Non-Hydrogen Bond: " << Binder->leftatom->Name << " and " << Binder->rightatom->Name << endl;2559 FragmentList->ListOfMolecules[No] = new molecule(elemente);2560 // initialise marker list for all atoms2561 for (int i=0;i<AtomCount;i++)2562 AddedAtomList[i] = NULL;2563 for (int i=0;i<BondCount;i++)2564 AddedBondList[i] = NULL;2565 2566 // add root bond as first bond (this is needed later on fragmenting)2567 *out << Verbose(1) << "Adding Root Bond " << *Binder << " and its atom." << endl;2568 AddedAtomList[Binder->leftatom->nr] = FragmentList->ListOfMolecules[No]->AddCopyAtom(Binder->leftatom);2569 AddedAtomList[Binder->rightatom->nr] = FragmentList->ListOfMolecules[No]->AddCopyAtom(Binder->rightatom);2570 AddedBondList[Binder->nr] = FragmentList->ListOfMolecules[No]->AddBond(AddedAtomList[Binder->leftatom->nr], AddedAtomList[Binder->rightatom->nr], Binder->BondDegree);2571 2572 // tag and add all atoms that have to be included2573 *out << Verbose(1) << "Adding BFS-wise on left hand side." << endl;2574 BreadthFirstSearchAdd(out, FragmentList->ListOfMolecules[No], AddedAtomList, AddedBondList, Binder->leftatom, NULL, BondOrder, IsAngstroem, CutCyclic);2575 *out << Verbose(1) << "Adding BFS-wise on right hand side." << endl;2576 BreadthFirstSearchAdd(out, FragmentList->ListOfMolecules[No], AddedAtomList, AddedBondList, Binder->rightatom, NULL, BondOrder, IsAngstroem, CutCyclic);2577 2578 // count atoms2579 FragmentList->ListOfMolecules[No]->CountAtoms(out);2580 FragmentList->TEList[No] = 1.;2581 *out << Verbose(1) << "GetBondFragmentOfOrder: " << Binder->nr << "th Fragment: " << FragmentList->ListOfMolecules[No] << "." << endl;2582 No++;2583 }2584 }2585 // free all lists2586 Free((void **)&AddedAtomList, "molecule::GetBondFragmentOfOrder: **AddedAtomList");2587 Free((void **)&AddedBondList, "molecule::GetBondFragmentOfOrder: **AddedBondList");2588 // output and exit2589 FragmentList->Output(out);2590 *out << Verbose(0) << "End of GetEachBondFragmentOfOrder." << endl;2591 return (FragmentList);2592 };2593 2594 2424 /** Adds atoms up to \a BondCount distance from \a *Root and notes them down in \a **AddedAtomList. 2595 2425 * Gray vertices are always enqueued in an AtomStackClass FIFO queue, the rest is usual BFS with adding vertices found was … … 2603 2433 * \param BondOrder maximum distance for vertices to add 2604 2434 * \param IsAngstroem lengths are in angstroem or bohrradii 2605 * \param CutCyclic whether to cut cyclic bonds (means saturate on need with hydrogen) or to always add2606 2435 */ 2607 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem , enum CutCyclicBond CutCyclic)2436 void molecule::BreadthFirstSearchAdd(ofstream *out, molecule *Mol, atom **&AddedAtomList, bond **&AddedBondList, atom *Root, bond *Bond, int BondOrder, bool IsAngstroem) 2608 2437 { 2609 2438 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::BreadthFirstSearchAdd: **PredecessorList"); … … 2650 2479 ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1; 2651 2480 *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; 2652 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond)) || (Binder->Cyclic && (CutCyclic == KeepBond))) ) { // Check for maximum distance2481 if ((((ShortestPathList[OtherAtom->nr] < BondOrder) && (Binder != Bond))) ) { // Check for maximum distance 2653 2482 *out << Verbose(3); 2654 2483 if (AddedAtomList[OtherAtom->nr] == NULL) { // add if it's not been so far … … 2678 2507 else if (ShortestPathList[OtherAtom->nr] >= BondOrder) 2679 2508 *out << Verbose(3) << "Not Queueing, is out of Bond Count of " << BondOrder; 2680 if ((Binder->Cyclic && (CutCyclic != KeepBond)))2681 *out << ", is part of a cyclic bond yet we don't keep them, saturating bond with Hydrogen." << endl;2682 2509 if (!Binder->Cyclic) 2683 2510 *out << ", is not part of a cyclic bond, saturating bond with Hydrogen." << endl; 2684 2511 if (AddedBondList[Binder->nr] == NULL) { 2685 if ((AddedAtomList[OtherAtom->nr] != NULL) && (CutCyclic == KeepBond)) { // .. whether we add or saturate2512 if ((AddedAtomList[OtherAtom->nr] != NULL)) { // .. whether we add or saturate 2686 2513 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 2687 2514 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 2698 2525 // This has to be a cyclic bond, check whether it's present ... 2699 2526 if (AddedBondList[Binder->nr] == NULL) { 2700 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder) || (CutCyclic == KeepBond))) {2527 if ((Binder != Bond) && (Binder->Cyclic) && (((ShortestPathList[Walker->nr]+1) < BondOrder))) { 2701 2528 AddedBondList[Binder->nr] = Mol->AddBond(AddedAtomList[Walker->nr], AddedAtomList[OtherAtom->nr], Binder->BondDegree); 2702 2529 AddedBondList[Binder->nr]->Cyclic = Binder->Cyclic; … … 3106 2933 bool **UsedList; 3107 2934 bond **BondsPerSPList; 3108 double TEFactor;3109 2935 int *BondsPerSPCount; 3110 2936 }; … … 3165 2991 *out << Verbose(2+verbosity) << "Adding " << *OtherWalker << " with nr " << OtherWalker->nr << "." << endl; 3166 2992 TouchedList[TouchedIndex++] = OtherWalker->nr; // note as added 3167 FragmentSearch->FragmentSet->insert(OtherWalker-> GetTrueFather()->nr);2993 FragmentSearch->FragmentSet->insert(OtherWalker->nr); 3168 2994 //FragmentSearch->UsedList[OtherWalker->nr][i] = true; 3169 2995 //} … … 3205 3031 *out << Verbose(1+verbosity) << "Enough items on stack for a fragment!" << endl; 3206 3032 // store fragment as a KeySet 3207 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], indices are: "; 3208 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) { 3209 *out << (*runner)+1 << " "; 3210 } 3033 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch->FragmentCounter << "], local nr.s are: "; 3034 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3035 *out << (*runner) << " "; 3211 3036 InsertFragmentIntoGraph(out, FragmentSearch); 3212 Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList);3037 //Removal = LookForRemovalCandidate(out, FragmentSearch->FragmentSet, FragmentSearch->ShortestPathList); 3213 3038 //Removal = StoreFragmentFromStack(out, FragmentSearch->Root, FragmentSearch->Leaflet, FragmentSearch->FragmentStack, FragmentSearch->ShortestPathList,FragmentSearch->Labels, &FragmentSearch->FragmentCounter, FragmentSearch->configuration); 3214 3039 } … … 3218 3043 for(int j=0;j<TouchedIndex;j++) { 3219 3044 Removal = TouchedList[j]; 3220 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal +1<< " from snake stack." << endl;3045 *out << Verbose(2+verbosity) << "Removing item nr. " << Removal << " from snake stack." << endl; 3221 3046 FragmentSearch->FragmentSet->erase(Removal); 3222 3047 TouchedList[j] = -1; 3223 3048 } 3049 *out << Verbose(2) << "Remaining local nr.s on snake stack are: "; 3050 for(KeySet::iterator runner = FragmentSearch->FragmentSet->begin(); runner != FragmentSearch->FragmentSet->end(); runner++) 3051 *out << (*runner) << " "; 3052 *out << endl; 3224 3053 TouchedIndex = 0; // set Index to 0 for list of atoms added on this level 3225 3054 } else { … … 3228 3057 } 3229 3058 Free((void **)&TouchedList, "molecule::SPFragmentGenerator: *TouchedList"); 3230 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl;3231 }; 3232 3233 /** Creates a list of all unique fragments of certain vertex size from a given graph \a Fragment in the context of \a this molecule.3059 *out << Verbose(1+verbosity) << "End of SPFragmentGenerator, " << RootDistance << " away from Root " << *FragmentSearch->Root << " and SubOrder is " << SubOrder << "." << endl; 3060 }; 3061 3062 /** Creates a list of all unique fragments of certain vertex size from a given graph \a Fragment for a given root vertex in the context of \a this molecule. 3234 3063 * Note that we may use the fact that the atoms are SP-ordered on the atomstack. I.e. when popping always the last, we first get all 3235 3064 * with SP of 2, then those with SP of 3, then those with SP of 4 and so on. 3236 3065 * \param *out output stream for debugging 3237 * \param Order number of vertices 3238 * \param *ListOfGraph Graph structure to insert found fragments into 3239 * \param Fragment Restricted vertex set to use in context of molecule 3240 * \param TEFactor TEFactor to store in graphlist in the end 3241 * \param *configuration configuration needed for IsAngstroem 3066 * \param Order bond order (limits BFS exploration and "number of digits" in power set generation 3067 * \param *ReturnKeySets Graph structure to insert found keysets/fragments into 3068 * \param RestrictedKeySet Restricted vertex set to use in context of molecule 3069 * \param RootKeyNr Atom::nr of the atom acting as current fragment root 3242 3070 * \return number of inserted fragments 3243 3071 * \note ShortestPathList in FragmentSearch structure is probably due to NumberOfAtomsSPLevel and SP not needed anymore 3244 3072 */ 3245 int molecule:: CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, Graph *ListOfGraph, KeySet Fragment, double TEFactor, config *configuration)3246 { 3247 int SP, UniqueIndex, RootKeyNr,AtomKeyNr;3248 int *NumberOfAtomsSPLevel = (int *) Malloc(sizeof(int)*Order, "molecule:: CreateListOfUniqueFragmentsOfOrder: *SPLevelCount");3073 int molecule::PowerSetGenerator(ofstream *out, int Order, Graph *ReturnKeySets, KeySet RestrictedKeySet, int RootKeyNr) 3074 { 3075 int SP, UniqueIndex, AtomKeyNr; 3076 int *NumberOfAtomsSPLevel = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *SPLevelCount"); 3249 3077 atom *Walker = NULL, *OtherWalker = NULL; 3250 3078 bond *Binder = NULL; 3251 3079 bond **BondsList = NULL; 3252 KeyStack RootStack;3253 3080 KeyStack AtomStack; 3254 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule:: CreateListOfUniqueFragmentsOfOrder: **PredecessorList");3081 atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::PowerSetGenerator: **PredecessorList"); 3255 3082 KeySet::iterator runner; 3083 //int Count = RestrictedKeySet.size(); 3256 3084 3257 3085 // initialise the fragments structure 3258 3086 struct UniqueFragments FragmentSearch; 3259 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule:: CreateListOfUniqueFragmentsOfOrder: ***BondsPerSPList");3260 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule:: CreateListOfUniqueFragmentsOfOrder: *BondsPerSPCount");3261 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule:: CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");3262 FragmentSearch.Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule:: CreateListOfUniqueFragmentsOfOrder: *Labels");3087 FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList"); 3088 FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount"); 3089 FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList"); 3090 FragmentSearch.Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *Labels"); 3263 3091 FragmentSearch.FragmentCounter = 0; 3264 3092 FragmentSearch.FragmentSet = new KeySet; 3265 FragmentSearch.configuration = configuration; 3266 FragmentSearch.TEFactor = TEFactor; 3267 FragmentSearch.Leaflet = ListOfGraph; // set to insertion graph 3093 FragmentSearch.Leaflet = ReturnKeySets; // set to insertion graph 3094 FragmentSearch.Root = FindAtom(RootKeyNr); 3268 3095 for (int i=0;i<AtomCount;i++) { 3269 3096 FragmentSearch.Labels[i] = -1; … … 3280 3107 3281 3108 *out << endl; 3282 *out << Verbose(0) << "Begin of CreateListOfUniqueFragmentsOfOrder with order " << Order << "." << endl; 3283 3284 RootStack.clear(); 3285 // find first root candidates 3286 runner = Fragment.begin(); 3287 Walker = NULL; 3288 while ((Walker == NULL) && (runner != Fragment.end())) { // search for first non-hydrogen atom 3289 Walker = FindAtom((*runner)); 3290 *out << Verbose(4) << "Current Root candidate is " << Walker->Name << "." << endl; 3109 *out << Verbose(0) << "Begin of PowerSetGenerator with order " << Order << " at Root " << *FragmentSearch.Root << "." << endl; 3110 3111 UniqueIndex = 0; 3112 if (FragmentSearch.Labels[RootKeyNr] == -1) 3113 FragmentSearch.Labels[RootKeyNr] = UniqueIndex++; 3114 FragmentSearch.ShortestPathList[RootKeyNr] = 0; 3115 // prepare the atom stack counters (number of atoms with certain SP on stack) 3116 for (int i=0;i<Order;i++) 3117 NumberOfAtomsSPLevel[i] = 0; 3118 NumberOfAtomsSPLevel[0] = 1; // for root 3119 SP = -1; 3120 *out << endl; 3121 *out << Verbose(0) << "Starting BFS analysis ..." << endl; 3122 // push as first on atom stack and goooo ... 3123 AtomStack.clear(); 3124 AtomStack.push_back(RootKeyNr); 3125 *out << Verbose(0) << "Cleared AtomStack and pushed root as first item onto it." << endl; 3126 // do a BFS search to fill the SP lists and label the found vertices 3127 while (!AtomStack.empty()) { 3128 // pop next atom 3129 AtomKeyNr = AtomStack.front(); 3130 AtomStack.pop_front(); 3131 if (SP != -1) 3132 NumberOfAtomsSPLevel[SP]--; 3133 if ((SP == -1) || (NumberOfAtomsSPLevel[SP] == -1)) { 3134 SP++; 3135 NumberOfAtomsSPLevel[SP]--; // carry over "-1" to next level 3136 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with 0 item(s)"; 3137 if (SP > 0) 3138 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3139 else 3140 *out << "." << endl; 3141 FragmentSearch.BondsPerSPCount[SP] = 0; 3142 } else { 3143 *out << Verbose(1) << "Still " << NumberOfAtomsSPLevel[SP]+1 << " on this SP (" << SP << ") level, currently having " << FragmentSearch.BondsPerSPCount[SP] << " item(s)." << endl; 3144 } 3145 Walker = FindAtom(AtomKeyNr); 3146 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and label " << FragmentSearch.Labels[AtomKeyNr] << " and SP of " << SP << "." << endl; 3147 // check for new sp level 3148 // go through all its bonds 3149 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3150 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3151 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3152 OtherWalker = Binder->GetOtherAtom(Walker); 3153 if ((RestrictedKeySet.find(OtherWalker->nr) != RestrictedKeySet.end()) 3291 3154 #ifdef ADDHYDROGEN 3292 if (Walker->type->Z == 1) // skip hydrogen 3293 Walker = NULL; 3155 && (OtherWalker->type->Z != 1) 3294 3156 #endif 3295 runner++; 3296 } 3297 if (Walker != NULL) 3298 RootStack.push_back(Walker->nr); 3299 else 3300 *out << Verbose(0) << "ERROR: Could not find an appropriate Root atom!" << endl; 3301 3302 UniqueIndex = 0; 3303 while (!RootStack.empty()) { 3304 // Get Root and prepare 3305 RootKeyNr = RootStack.front(); 3306 RootStack.pop_front(); 3307 FragmentSearch.Root = FindAtom(RootKeyNr); 3308 if (FragmentSearch.Labels[RootKeyNr] == -1) 3309 FragmentSearch.Labels[RootKeyNr] = UniqueIndex++; 3310 FragmentSearch.ShortestPathList[RootKeyNr] = 0; 3311 // prepare the atom stack counters (number of atoms with certain SP on stack) 3312 for (int i=0;i<Order;i++) 3313 NumberOfAtomsSPLevel[i] = 0; 3314 NumberOfAtomsSPLevel[0] = 1; // for root 3315 SP = -1; 3316 *out << endl; 3317 *out << Verbose(0) << "Starting BFS analysis with current Root: " << *FragmentSearch.Root << "." << endl; 3318 // push as first on atom stack and goooo ... 3319 AtomStack.clear(); 3320 AtomStack.push_back(RootKeyNr); 3321 *out << Verbose(0) << "Cleared AtomStack and pushed root as first item onto it." << endl; 3322 // do a BFS search to fill the SP lists and label the found vertices 3323 while (!AtomStack.empty()) { 3324 // pop next atom 3325 AtomKeyNr = AtomStack.front(); 3326 AtomStack.pop_front(); 3327 if (SP != -1) 3328 NumberOfAtomsSPLevel[SP]--; 3329 if ((SP == -1) || (NumberOfAtomsSPLevel[SP] == -1)) { 3330 ////if (SP < FragmentSearch.ShortestPathList[AtomKeyNr]) { // bfs has reached new SP level, hence allocate for new list 3331 SP++; 3332 NumberOfAtomsSPLevel[SP]--; // carry over "-1" to next level 3333 ////SP = FragmentSearch.ShortestPathList[AtomKeyNr]; 3334 *out << Verbose(1) << "New SP level reached: " << SP << ", creating new SP list with 0 item(s)"; 3335 if (SP > 0) 3336 *out << ", old level closed with " << FragmentSearch.BondsPerSPCount[SP-1] << " item(s)." << endl; 3337 else 3338 *out << "." << endl; 3339 FragmentSearch.BondsPerSPCount[SP] = 0; 3340 } else { 3341 *out << Verbose(1) << "Still " << NumberOfAtomsSPLevel[SP]+1 << " on this SP (" << SP << ") level, currently having " << FragmentSearch.BondsPerSPCount[SP] << " item(s)." << endl; 3342 } 3343 Walker = FindAtom(AtomKeyNr); 3344 *out << Verbose(0) << "Current Walker is: " << *Walker << " with nr " << Walker->nr << " and label " << FragmentSearch.Labels[AtomKeyNr] << " and SP of " << SP << "." << endl; 3345 // check for new sp level 3346 // go through all its bonds 3347 *out << Verbose(1) << "Going through all bonds of Walker." << endl; 3348 for (int i=0;i<NumberOfBondsPerAtom[AtomKeyNr];i++) { 3349 Binder = ListOfBondsPerAtom[AtomKeyNr][i]; 3350 OtherWalker = Binder->GetOtherAtom(Walker); 3351 if ((Fragment.find(OtherWalker->nr) != Fragment.end()) 3352 #ifdef ADDHYDROGEN 3353 && (OtherWalker->type->Z != 1) 3354 #endif 3355 ) { // skip hydrogens and restrict to fragment 3356 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 3357 // set the label if not set (and push on root stack as well) 3358 if (FragmentSearch.Labels[OtherWalker->nr] == -1) { 3359 RootStack.push_back(OtherWalker->nr); 3360 FragmentSearch.Labels[OtherWalker->nr] = UniqueIndex++; 3361 *out << Verbose(3) << "Set label to " << FragmentSearch.Labels[OtherWalker->nr] << "." << endl; 3362 } else { 3363 *out << Verbose(3) << "Label is already " << FragmentSearch.Labels[OtherWalker->nr] << "." << endl; 3364 } 3365 if ((OtherWalker != PredecessorList[AtomKeyNr]) && (FragmentSearch.Labels[OtherWalker->nr] > FragmentSearch.Labels[RootKeyNr])) { // only pass through those with label bigger than Root's 3366 // set shortest path if not set or longer 3367 //if ((FragmentSearch.ShortestPathList[OtherWalker->nr] == -1) || (FragmentSearch.ShortestPathList[OtherWalker->nr] > FragmentSearch.ShortestPathList[AtomKeyNr])) { 3368 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 3369 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3370 //} else { 3371 // *out << Verbose(3) << "Shortest Path is already " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3372 //} 3373 if (FragmentSearch.ShortestPathList[OtherWalker->nr] < Order) { // only pass through those within reach of Order 3374 // push for exploration on stack (only if the SP of OtherWalker is longer than of Walker! (otherwise it has been added already!) 3375 if (FragmentSearch.ShortestPathList[OtherWalker->nr] > SP) { 3376 if (FragmentSearch.ShortestPathList[OtherWalker->nr] < (Order-1)) { 3377 *out << Verbose(3) << "Putting on atom stack for further exploration." << endl; 3378 PredecessorList[OtherWalker->nr] = Walker; // note down the one further up the exploration tree 3379 AtomStack.push_back(OtherWalker->nr); 3380 NumberOfAtomsSPLevel[FragmentSearch.ShortestPathList[OtherWalker->nr]]++; 3381 } else { 3382 *out << Verbose(3) << "Not putting on atom stack, is at end of reach." << endl; 3383 } 3384 // add the bond in between to the SP list 3385 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 3386 add(Binder, FragmentSearch.BondsPerSPList[2*SP+1]); 3387 FragmentSearch.BondsPerSPCount[SP]++; 3388 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP] << " item(s)." << endl; 3157 ) { // skip hydrogens and restrict to fragment 3158 *out << Verbose(2) << "Current partner is " << *OtherWalker << " with nr " << OtherWalker->nr << " in bond " << *Binder << "." << endl; 3159 // set the label if not set (and push on root stack as well) 3160 if (FragmentSearch.Labels[OtherWalker->nr] == -1) { 3161 FragmentSearch.Labels[OtherWalker->nr] = UniqueIndex++; 3162 *out << Verbose(3) << "Set label to " << FragmentSearch.Labels[OtherWalker->nr] << "." << endl; 3163 } else { 3164 *out << Verbose(3) << "Label is already " << FragmentSearch.Labels[OtherWalker->nr] << "." << endl; 3165 } 3166 if ((OtherWalker != PredecessorList[AtomKeyNr]) && (FragmentSearch.Labels[OtherWalker->nr] > FragmentSearch.Labels[RootKeyNr])) { // only pass through those with label bigger than Root's 3167 FragmentSearch.ShortestPathList[OtherWalker->nr] = SP+1; 3168 *out << Verbose(3) << "Set Shortest Path to " << FragmentSearch.ShortestPathList[OtherWalker->nr] << "." << endl; 3169 if (FragmentSearch.ShortestPathList[OtherWalker->nr] < Order) { // only pass through those within reach of Order 3170 // push for exploration on stack (only if the SP of OtherWalker is longer than of Walker! (otherwise it has been added already!) 3171 if (FragmentSearch.ShortestPathList[OtherWalker->nr] > SP) { 3172 if (FragmentSearch.ShortestPathList[OtherWalker->nr] < (Order-1)) { 3173 *out << Verbose(3) << "Putting on atom stack for further exploration." << endl; 3174 PredecessorList[OtherWalker->nr] = Walker; // note down the one further up the exploration tree 3175 AtomStack.push_back(OtherWalker->nr); 3176 NumberOfAtomsSPLevel[FragmentSearch.ShortestPathList[OtherWalker->nr]]++; 3389 3177 } else { 3390 *out << Verbose(3) << "Not putting on atom stack, nor adding bond, as " << *OtherWalker << "'s SP is shorter than Walker's." << endl;3178 *out << Verbose(3) << "Not putting on atom stack, is at end of reach." << endl; 3391 3179 } 3392 } else { 3393 *out << Verbose(3) << "Not continuing, as " << *OtherWalker << " is out of reach of order " << Order << "." << endl; 3394 } 3395 } else { 3396 *out << Verbose(3) << "Not passing on, as label of " << *OtherWalker << " " << FragmentSearch.Labels[OtherWalker->nr] << " is smaller than that of Root " << FragmentSearch.Labels[RootKeyNr] << " or this is my predecessor." << endl; 3397 } 3398 } else { 3399 *out << Verbose(2) << "Is not in the Fragment or skipping hydrogen " << *OtherWalker << "." << endl; 3400 } 3401 } 3402 } 3403 // reset predecessor list 3404 for(int i=0;i<Order;i++) { 3405 Binder = FragmentSearch.BondsPerSPList[2*i]; 3406 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3407 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3180 // add the bond in between to the SP list 3181 Binder = new bond(Walker, OtherWalker); // create a new bond in such a manner, that bond::rightatom is always the one more distant 3182 add(Binder, FragmentSearch.BondsPerSPList[2*SP+1]); 3183 FragmentSearch.BondsPerSPCount[SP]++; 3184 *out << Verbose(3) << "Added its bond to SP list, having now " << FragmentSearch.BondsPerSPCount[SP] << " item(s)." << endl; 3185 } else *out << Verbose(3) << "Not putting on atom stack, nor adding bond, as " << *OtherWalker << "'s SP is shorter than Walker's." << endl; 3186 } else *out << Verbose(3) << "Not continuing, as " << *OtherWalker << " is out of reach of order " << Order << "." << endl; 3187 } else *out << Verbose(3) << "Not passing on, as label of " << *OtherWalker << " " << FragmentSearch.Labels[OtherWalker->nr] << " is smaller than that of Root " << FragmentSearch.Labels[RootKeyNr] << " or this is my predecessor." << endl; 3188 } else *out << Verbose(2) << "Is not in the retstricted keyset or skipping hydrogen " << *OtherWalker << "." << endl; 3189 } 3190 } 3191 // reset predecessor list 3192 for(int i=0;i<Order;i++) { 3193 Binder = FragmentSearch.BondsPerSPList[2*i]; 3194 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3195 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3196 Binder = Binder->next; 3197 PredecessorList[Binder->rightatom->nr] = NULL; // By construction "OtherAtom" is always Bond::rightatom! 3198 } 3199 } 3200 *out << endl; 3201 3202 // outputting all list for debugging 3203 *out << Verbose(0) << "Printing all found lists." << endl; 3204 for(int i=0;i<Order;i++) { 3205 Binder = FragmentSearch.BondsPerSPList[2*i]; 3206 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3207 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3208 Binder = Binder->next; 3209 *out << Verbose(2) << *Binder << endl; 3210 } 3211 } 3212 3213 // creating fragments with the found edge sets 3214 SP = 0; 3215 for(int i=0;i<Order;i++) { // sum up all found edges 3216 Binder = FragmentSearch.BondsPerSPList[2*i]; 3217 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3218 Binder = Binder->next; 3219 SP ++; 3220 } 3221 } 3222 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 3223 if (SP >= (Order-1)) { 3224 // start with root (push on fragment stack) 3225 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << ", local nr is " << FragmentSearch.Root->nr << "." << endl; 3226 FragmentSearch.FragmentSet->clear(); 3227 FragmentSearch.FragmentSet->insert(FragmentSearch.Root->nr); 3228 3229 if (FragmentSearch.FragmentSet->size() == (unsigned int) Order) { 3230 *out << Verbose(0) << "Enough items on stack already for a fragment!" << endl; 3231 // store fragment as a KeySet 3232 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch.FragmentCounter << "], local nr.s are: "; 3233 for(KeySet::iterator runner = FragmentSearch.FragmentSet->begin(); runner != FragmentSearch.FragmentSet->end(); runner++) { 3234 *out << (*runner) << " "; 3235 } 3236 *out << endl; 3237 InsertFragmentIntoGraph(out, &FragmentSearch); 3238 } else { 3239 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 3240 // prepare the subset and call the generator 3241 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::PowerSetGenerator: **BondsList"); 3242 Binder = FragmentSearch.BondsPerSPList[0]; 3243 for(int i=0;i<FragmentSearch.BondsPerSPCount[0];i++) { 3408 3244 Binder = Binder->next; 3409 PredecessorList[Binder->rightatom->nr] = NULL; // By construction "OtherAtom" is always Bond::rightatom! 3410 } 3411 } 3412 *out << endl; 3413 *out << Verbose(0) << "Printing all found lists." << endl; 3414 // outputting all list for debugging 3415 for(int i=0;i<Order;i++) { 3416 Binder = FragmentSearch.BondsPerSPList[2*i]; 3417 *out << Verbose(1) << "Current SP level is " << i << "." << endl; 3418 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3419 Binder = Binder->next; 3420 *out << Verbose(2) << *Binder << endl; 3421 } 3422 } 3423 3424 // creating fragments with the found edge sets 3425 SP = 0; 3426 for(int i=0;i<Order;i++) { // sum up all found edges 3427 Binder = FragmentSearch.BondsPerSPList[2*i]; 3428 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3429 Binder = Binder->next; 3430 SP ++; 3431 } 3432 } 3433 *out << Verbose(0) << "Total number of edges is " << SP << "." << endl; 3434 if (SP >= (Order-1)) { 3435 // start with root (push on fragment stack) 3436 *out << Verbose(0) << "Starting fragment generation with " << *FragmentSearch.Root << "." << endl; 3437 FragmentSearch.FragmentSet->clear(); 3438 FragmentSearch.FragmentSet->insert(FragmentSearch.Root->GetTrueFather()->nr); 3439 3440 if (FragmentSearch.FragmentSet->size() == (unsigned int) Order) { 3441 *out << Verbose(0) << "Enough items on stack already for a fragment!" << endl; 3442 // store fragment as a KeySet 3443 *out << Verbose(2) << "Found a new fragment[" << FragmentSearch.FragmentCounter << "], indices are: "; 3444 for(KeySet::iterator runner = FragmentSearch.FragmentSet->begin(); runner != FragmentSearch.FragmentSet->end(); runner++) { 3445 *out << (*runner)+1 << " "; 3446 } 3447 *out << endl; 3448 InsertFragmentIntoGraph(out, &FragmentSearch); 3449 //StoreFragmentFromStack(out, FragmentSearch.Root, FragmentSearch.Leaflet, FragmentSearch.FragmentStack, FragmentSearch.ShortestPathList,FragmentSearch.Labels, &FragmentSearch.FragmentCounter, FragmentSearch.configuration); 3450 } else { 3451 *out << Verbose(0) << "Preparing subset for this root and calling generator." << endl; 3452 // prepare the subset and call the generator 3453 BondsList = (bond **) Malloc(sizeof(bond *)*FragmentSearch.BondsPerSPCount[0], "molecule::CreateListOfUniqueFragmentsOfOrder: **BondsList"); 3454 Binder = FragmentSearch.BondsPerSPList[0]; 3455 for(int i=0;i<FragmentSearch.BondsPerSPCount[0];i++) { 3456 Binder = Binder->next; 3457 BondsList[i] = Binder; 3458 } 3459 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order-1); 3460 Free((void **)&BondsList, "molecule::CreateListOfUniqueFragmentsOfOrder: **BondsList"); 3461 } 3462 } else { 3463 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 3464 } 3465 3466 // remove root from stack 3467 *out << Verbose(0) << "Removing root again from stack." << endl; 3468 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 3469 3470 // free'ing the bonds lists 3471 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 3472 for(int i=0;i<Order;i++) { 3473 *out << Verbose(1) << "Current SP level is " << i << ": "; 3474 Binder = FragmentSearch.BondsPerSPList[2*i]; 3475 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3476 Binder = Binder->next; 3477 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 3478 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 3479 } 3480 // delete added bonds 3481 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 3482 // also start and end node 3483 *out << "cleaned." << endl; 3484 } 3485 } 3486 3245 BondsList[i] = Binder; 3246 } 3247 SPFragmentGenerator(out, &FragmentSearch, 0, BondsList, FragmentSearch.BondsPerSPCount[0], Order-1); 3248 Free((void **)&BondsList, "molecule::PowerSetGenerator: **BondsList"); 3249 } 3250 } else { 3251 *out << Verbose(0) << "Not enough total number of edges to build " << Order << "-body fragments." << endl; 3252 } 3253 3254 /* // as FragmentSearch structure is used only once, we don't have to clean it anymore 3255 // remove root from stack 3256 *out << Verbose(0) << "Removing root again from stack." << endl; 3257 FragmentSearch.FragmentSet->erase(FragmentSearch.Root->nr); 3258 3259 // free'ing the bonds lists 3260 *out << Verbose(0) << "Free'ing all found lists. and resetting index lists" << endl; 3261 for(int i=0;i<Order;i++) { 3262 *out << Verbose(1) << "Current SP level is " << i << ": "; 3263 Binder = FragmentSearch.BondsPerSPList[2*i]; 3264 while (Binder->next != FragmentSearch.BondsPerSPList[2*i+1]) { 3265 Binder = Binder->next; 3266 // *out << "Removing atom " << Binder->leftatom->nr << " and " << Binder->rightatom->nr << "." << endl; // make sure numbers are local 3267 FragmentSearch.ShortestPathList[Binder->leftatom->nr] = -1; 3268 FragmentSearch.ShortestPathList[Binder->rightatom->nr] = -1; 3269 } 3270 // delete added bonds 3271 cleanup(FragmentSearch.BondsPerSPList[2*i], FragmentSearch.BondsPerSPList[2*i+1]); 3272 // also start and end node 3273 *out << "cleaned." << endl; 3274 } 3275 */ 3487 3276 // free allocated memory 3488 Free((void **)&NumberOfAtomsSPLevel, "molecule:: CreateListOfUniqueFragmentsOfOrder: *SPLevelCount");3489 Free((void **)&PredecessorList, "molecule:: CreateListOfUniqueFragmentsOfOrder: **PredecessorList");3277 Free((void **)&NumberOfAtomsSPLevel, "molecule::PowerSetGenerator: *SPLevelCount"); 3278 Free((void **)&PredecessorList, "molecule::PowerSetGenerator: **PredecessorList"); 3490 3279 for(int i=0;i<Order;i++) { // delete start and end of each list 3491 3280 delete(FragmentSearch.BondsPerSPList[2*i]); 3492 3281 delete(FragmentSearch.BondsPerSPList[2*i+1]); 3493 3282 } 3494 Free((void **)&FragmentSearch.BondsPerSPList, "molecule:: CreateListOfUniqueFragmentsOfOrder: ***BondsPerSPList");3495 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule:: CreateListOfUniqueFragmentsOfOrder: *BondsPerSPCount");3496 Free((void **)&FragmentSearch.ShortestPathList, "molecule:: CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");3497 Free((void **)&FragmentSearch.Labels, "molecule:: CreateListOfUniqueFragmentsOfOrder: *Labels");3283 Free((void **)&FragmentSearch.BondsPerSPList, "molecule::PowerSetGenerator: ***BondsPerSPList"); 3284 Free((void **)&FragmentSearch.BondsPerSPCount, "molecule::PowerSetGenerator: *BondsPerSPCount"); 3285 Free((void **)&FragmentSearch.ShortestPathList, "molecule::PowerSetGenerator: *ShortestPathList"); 3286 Free((void **)&FragmentSearch.Labels, "molecule::PowerSetGenerator: *Labels"); 3498 3287 delete(FragmentSearch.FragmentSet); 3499 3288 3500 // // gather all the leaves together3501 // *out << Verbose(0) << "Copying all fragments into MoleculeList structure." << endl;3502 // FragmentList = new Graph;3503 // UniqueIndex = 0;3504 // while ((FragmentSearch.Leaflet != NULL) && (UniqueIndex < FragmentSearch.FragmentCounter)) {3505 // FragmentList->insert();3506 // FragmentList->ListOfMolecules[UniqueIndex++] = FragmentSearch.Leaflet->Leaf;3507 // FragmentSearch.Leaflet->Leaf = NULL; // prevent molecule from being removed3508 // TempLeaf = FragmentSearch.Leaflet;3509 // FragmentSearch.Leaflet = FragmentSearch.Leaflet->previous;3510 // delete(TempLeaf);3511 // };3512 3513 3289 // return list 3514 *out << Verbose(0) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;3290 *out << Verbose(0) << "End of PowerSetGenerator." << endl; 3515 3291 return FragmentSearch.FragmentCounter; 3516 3292 }; … … 3664 3440 GraphTestPair testGraphInsert; 3665 3441 3666 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter, Fragment->TEFactor))); // store fragment number and current factor3442 testGraphInsert = Fragment->Leaflet->insert(GraphPair (*Fragment->FragmentSet,pair<int,double>(Fragment->FragmentCounter,1))); // store fragment number and current factor 3667 3443 if (testGraphInsert.second) { 3668 3444 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " successfully inserted." << endl; … … 3670 3446 } else { 3671 3447 *out << Verbose(2) << "KeySet " << Fragment->FragmentCounter << " failed to insert, present fragment is " << ((*(testGraphInsert.first)).second).first << endl; 3672 ((*(testGraphInsert.first)).second).second + = Fragment->TEFactor;3448 ((*(testGraphInsert.first)).second).second ++; // increase the "created" counter 3673 3449 *out << Verbose(2) << "New factor is " << ((*(testGraphInsert.first)).second).second << "." << endl; 3674 3450 } … … 3687 3463 * \param graph1 first (dest) graph 3688 3464 * \param graph2 second (source) graph 3465 * \param *counter keyset counter that gets increased 3689 3466 */ 3690 3467 inline void InsertGraphIntoGraph(ofstream *out, Graph &graph1, Graph &graph2, int *counter) … … 3705 3482 3706 3483 3707 /** Creates truncated BOSSANOVA expansion up to order \a k. 3484 /** Performs BOSSANOVA decomposition at selected sites, increasing the cutoff by one at these sites. 3485 * Important only is that we create all fragments, it is not important if we create them more than once 3486 * as these copies are filtered out via use of the hash table (KeySet). 3708 3487 * \param *out output stream for debugging 3709 * \param ANOVAOrder ANOVA expansion is truncated above this order3710 * \param *configuration configuration for writing config files for each fragment3711 3488 * \return pointer to Graph list 3712 3489 */ 3713 Graph * molecule::FragmentBOSSANOVA(ofstream *out, int ANOVAOrder, config *configuration)3490 Graph * molecule::FragmentBOSSANOVA(ofstream *out, KeyStack &RootStack) 3714 3491 { 3715 3492 Graph *FragmentList = NULL, ***FragmentLowerOrdersList = NULL; 3716 //MoleculeListClass *FragmentMoleculeList = NULL;3717 3493 int Order, NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL; 3718 3494 int counter = 0; 3495 int UpgradeCount = RootStack.size(); 3496 KeyStack FragmentRootStack; 3497 int RootKeyNr, RootNr; 3719 3498 3720 3499 *out << Verbose(0) << "Begin of FragmentBOSSANOVA." << endl; … … 3722 3501 // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5) 3723 3502 // with all needed lower orders that are subtracted, the other dimension is the BondOrder (i.e. from 1 to 5) 3724 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)* ANOVAOrder, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder");3725 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)* ANOVAOrder, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList");3726 3727 // Construct the complete KeySet 3503 NumMoleculesOfOrder = (int *) Malloc(sizeof(int)*UpgradeCount, "molecule::FragmentBOSSANOVA: *NumMoleculesOfOrder"); 3504 FragmentLowerOrdersList = (Graph ***) Malloc(sizeof(Graph **)*UpgradeCount, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); 3505 3506 // Construct the complete KeySet which we need for topmost level only (but for all Roots) 3728 3507 atom *Walker = start; 3729 3508 KeySet CompleteMolecule; … … 3733 3512 } 3734 3513 3735 for (int BondOrder=1;BondOrder<=ANOVAOrder;BondOrder++) { 3736 // 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 3737 // 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), 3738 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 3739 // 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) 3740 NumLevels = 1 << (BondOrder-1); // (int)pow(2,BondOrder-1); 3741 *out << Verbose(0) << "BondOrder is (" << BondOrder << "/" << ANOVAOrder << ") and NumLevels is " << NumLevels << "." << endl; 3742 3514 // 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 3515 // 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), 3516 // hence we have overall four 2th order levels for splitting. This also allows for putting all into a single array (FragmentLowerOrdersList[]) 3517 // 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) 3518 RootNr = 0; // counts through the roots in RootStack 3519 while (RootNr < UpgradeCount) { 3520 RootKeyNr = RootStack.front(); 3521 RootStack.pop_front(); 3522 // increase adaptive order by one 3523 Walker = FindAtom(RootKeyNr); 3524 Walker->GetTrueFather()->AdaptiveOrder++; 3525 Order = Walker->AdaptiveOrder = Walker->GetTrueFather()->AdaptiveOrder; 3526 3743 3527 // allocate memory for all lower level orders in this 1D-array of ptrs 3744 FragmentLowerOrdersList[BondOrder-1] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 3528 NumLevels = 1 << (Order); // (int)pow(2,Order); 3529 FragmentLowerOrdersList[RootNr] = (Graph **) Malloc(sizeof(Graph *)*NumLevels, "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 3745 3530 3746 3531 // create top order where nothing is reduced 3747 3532 *out << Verbose(0) << "==============================================================================================================" << endl; 3748 *out << Verbose(0) << "Creating list of unique fragments of Bond Order " << BondOrder << " itself." << endl; 3533 *out << Verbose(0) << "Creating KeySets of Bond Order " << Order << " for " << *Walker << ", NumLevels is " << NumLevels << ", " << RootStack.size() << " Roots remaining." << endl; 3534 3749 3535 // Create list of Graphs of current Bond Order (i.e. F_{ij}) 3750 FragmentLowerOrdersList[ BondOrder-1][0] = new Graph;3751 NumMoleculesOfOrder[ BondOrder-1] = CreateListOfUniqueFragmentsOfOrder(out, BondOrder, FragmentLowerOrdersList[BondOrder-1][0], CompleteMolecule, 1., configuration);3752 *out << Verbose(1) << "Number of resulting molecules is: " << NumMoleculesOfOrder[BondOrder-1] << "." << endl;3536 FragmentLowerOrdersList[RootNr][0] = new Graph; 3537 NumMoleculesOfOrder[RootNr] = PowerSetGenerator(out, Walker->AdaptiveOrder, FragmentLowerOrdersList[RootNr][0], CompleteMolecule, RootKeyNr); 3538 *out << Verbose(1) << "Number of resulting KeySets is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 3753 3539 NumMolecules = 0; 3754 3540 3755 // create lower order fragments 3756 *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 3757 Order = BondOrder; 3758 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) 3759 3760 // step down to next order at (virtual) boundary of powers of 2 in array 3761 while (source >= (1 << (BondOrder-Order))) // (int)pow(2,BondOrder-Order)) 3762 Order--; 3763 *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 3764 for (int SubOrder=Order;SubOrder>1;SubOrder--) { 3765 int dest = source + (1 << (BondOrder-SubOrder)); 3766 *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 3767 *out << Verbose(0) << "Current SubOrder is: " << SubOrder-1 << " with source " << source << " to destination " << dest << "." << endl; 3768 3769 // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 3770 //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[BondOrder-1][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 3771 //NumMolecules = 0; 3772 FragmentLowerOrdersList[BondOrder-1][dest] = new Graph; 3773 for(Graph::iterator runner = (*FragmentLowerOrdersList[BondOrder-1][source]).begin();runner != (*FragmentLowerOrdersList[BondOrder-1][source]).end(); runner++) { 3774 NumMolecules += CreateListOfUniqueFragmentsOfOrder(out,SubOrder-1, FragmentLowerOrdersList[BondOrder-1][dest], (*runner).first, -(*runner).second.second, configuration); 3541 if ((NumLevels >> 1) > 0) { 3542 // create lower order fragments 3543 *out << Verbose(0) << "Creating list of unique fragments of lower Bond Order terms to be subtracted." << endl; 3544 Order = Walker->AdaptiveOrder; 3545 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) 3546 // step down to next order at (virtual) boundary of powers of 2 in array 3547 while (source >= (1 << (Walker->AdaptiveOrder-Order))) // (int)pow(2,Walker->AdaptiveOrder-Order)) 3548 Order--; 3549 *out << Verbose(0) << "Current Order is: " << Order << "." << endl; 3550 for (int SubOrder=Order;SubOrder>1;SubOrder--) { 3551 int dest = source + (1 << (Walker->AdaptiveOrder-SubOrder)); 3552 *out << Verbose(0) << "--------------------------------------------------------------------------------------------------------------" << endl; 3553 *out << Verbose(0) << "Current SubOrder is: " << SubOrder-1 << " with source " << source << " to destination " << dest << "." << endl; 3554 3555 // every molecule is split into a list of again (Order - 1) molecules, while counting all molecules 3556 //*out << Verbose(1) << "Splitting the " << (*FragmentLowerOrdersList[RootNr][source]).size() << " molecules of the " << source << "th cell in the array." << endl; 3557 //NumMolecules = 0; 3558 FragmentLowerOrdersList[RootNr][dest] = new Graph; 3559 for(Graph::iterator runner = (*FragmentLowerOrdersList[RootNr][source]).begin();runner != (*FragmentLowerOrdersList[RootNr][source]).end(); runner++) { 3560 for (KeySet::iterator sprinter = (*runner).first.begin();sprinter != (*runner).first.end(); sprinter++) { 3561 FragmentList = new Graph(); 3562 PowerSetGenerator(out, SubOrder-1, FragmentList, (*runner).first, *sprinter); 3563 // insert new keysets FragmentList into FragmentLowerOrdersList[Walker->AdaptiveOrder-1][dest] 3564 *out << Verbose(1) << "Merging resulting key sets with those present in destination " << dest << "." << endl; 3565 InsertGraphIntoGraph(out, *FragmentLowerOrdersList[RootNr][dest], *FragmentList, &NumMolecules); 3566 delete(FragmentList); 3567 } 3568 } 3569 *out << Verbose(1) << "Number of resulting molecules for SubOrder " << SubOrder << " is: " << NumMolecules << "." << endl; 3775 3570 } 3776 *out << Verbose(1) << "Number of resulting molecules is: " << NumMolecules << "." << endl; 3777 } 3778 } 3779 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current BondOrder 3780 //NumMoleculesOfOrder[BondOrder-1] = NumMolecules; 3781 TotalNumMolecules += NumMoleculesOfOrder[BondOrder-1]; 3782 *out << Verbose(1) << "Number of resulting molecules for Order " << BondOrder << " is: " << NumMoleculesOfOrder[BondOrder-1] << "." << endl; 3783 } 3571 } 3572 } 3573 // now, we have completely filled each cell of FragmentLowerOrdersList[] for the current Walker->AdaptiveOrder 3574 //NumMoleculesOfOrder[Walker->AdaptiveOrder-1] = NumMolecules; 3575 TotalNumMolecules += NumMoleculesOfOrder[RootNr]; 3576 *out << Verbose(1) << "Number of resulting molecules for Order " << Walker->AdaptiveOrder << " is: " << NumMoleculesOfOrder[RootNr] << "." << endl; 3577 RootStack.push_back(RootKeyNr); // put back on stack 3578 RootNr++; 3579 } 3580 *out << Verbose(0) << "==============================================================================================================" << endl; 3784 3581 *out << Verbose(1) << "Total number of resulting molecules is: " << TotalNumMolecules << "." << endl; 3582 *out << Verbose(0) << "==============================================================================================================" << endl; 3785 3583 // now, FragmentLowerOrdersList is complete, it looks - for BondOrder 5 - as this (number is the ANOVA Order of the terms therein) 3786 3584 // 5433222211111111 … … 3789 3587 // 21 3790 3588 // 1 3791 // Subsequently, we combine same orders into a single list (FragmentByOrderList) and reduce these by order3589 // Subsequently, we combine all into a single list (FragmentList) 3792 3590 3793 3591 *out << Verbose(0) << "Combining the lists of all orders per order and finally into a single one." << endl; 3794 3592 FragmentList = new Graph; 3795 for (int BondOrder=1;BondOrder<=ANOVAOrder;BondOrder++) { 3796 NumLevels = 1 << (BondOrder-1); 3593 RootNr = 0; 3594 while (!RootStack.empty()) { 3595 RootKeyNr = RootStack.front(); 3596 RootStack.pop_front(); 3597 Walker = FindAtom(RootKeyNr); 3598 NumLevels = 1 << (Walker->AdaptiveOrder - 1); 3797 3599 for(int i=0;i<NumLevels;i++) { 3798 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[BondOrder-1][i]), &counter); 3799 delete(FragmentLowerOrdersList[BondOrder-1][i]); 3800 } 3801 Free((void **)&FragmentLowerOrdersList[BondOrder-1], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 3600 InsertGraphIntoGraph(out, *FragmentList, (*FragmentLowerOrdersList[RootNr][i]), &counter); 3601 delete(FragmentLowerOrdersList[RootNr][i]); 3602 } 3603 Free((void **)&FragmentLowerOrdersList[RootNr], "molecule::FragmentBOSSANOVA: **FragmentLowerOrdersList[]"); 3604 RootNr++; 3802 3605 } 3803 3606 Free((void **)&FragmentLowerOrdersList, "molecule::FragmentBOSSANOVA: ***FragmentLowerOrdersList"); … … 3807 3610 return FragmentList; 3808 3611 }; 3809 3810 /** Fragments a molecule, taking \a BondDegree neighbours into accent.3811 * First of all, we have to split up the molecule into bonds ranging out till \a BondDegree.3812 * These fragments serve in the following as the basis the calculate the bond energy of the bond3813 * they originated from. Thus, they are split up in a left and a right part, each calculated for3814 * the total energy, including the fragment as a whole and then we get:3815 * E(fragment) - E(left) - E(right) = E(bond)3816 * The splitting up is done via Breadth-First-Search, \sa BreadthFirstSearchAdd().3817 * \param *out output stream for debugging3818 * \param BondOrder up to how many neighbouring bonds a fragment contains3819 * \param *configuration configuration for writing config files for each fragment3820 * \param CutCyclic whether to add cut cyclic bond or to saturate3821 * \return pointer to MoleculeListClass with all the fragments or NULL if something went wrong.3822 */3823 MoleculeListClass * molecule::FragmentBottomUp(ofstream *out, int BondOrder, config *configuration, enum CutCyclicBond CutCyclic)3824 {3825 int Num;3826 MoleculeListClass *FragmentList = NULL, **FragmentsList = NULL;3827 bond *Bond = NULL;3828 3829 *out << Verbose(0) << "Begin of FragmentBottomUp." << endl;3830 FragmentsList = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*2, "molecule::FragmentBottomUp: **FragmentsList");3831 *out << Verbose(0) << "Getting Atomic fragments." << endl;3832 FragmentsList[0] = GetAtomicFragments(out, AtomCount, configuration->GetIsAngstroem(), 1., CutCyclic);3833 3834 // create the fragments including each one bond of the original molecule and up to \a BondDegree neighbours3835 *out << Verbose(0) << "Getting " <<3836 #ifdef ADDHYDROGEN3837 NoNonBonds3838 #else3839 BondCount3840 #endif3841 << " Bond fragments." << endl;3842 FragmentList = GetEachBondFragmentOfOrder(out, BondOrder, configuration->GetIsAngstroem(), CutCyclic);3843 3844 // check whether there are equal fragments by ReduceToUniqueOnes3845 FragmentList->ReduceToUniqueList(out, &cell_size[0], BondDistance);3846 3847 *out << Verbose(0) << "Begin of Separating " << FragmentList->NumberOfMolecules << " Fragments into Bond pieces." << endl;3848 // as we have the list, we have to take each fragment split it relative to its originating3849 // bond into left and right and store these in a new list3850 *out << Verbose(2) << endl << "Allocating MoleculeListClass" << endl;3851 FragmentsList[1] = new MoleculeListClass(3*FragmentList->NumberOfMolecules, AtomCount); // for each molecule the whole and its left and right part3852 *out << Verbose(2) << "Creating TEList." << endl;3853 // and create TE summation for these bond energy approximations (bond = whole - left - right)3854 for(int i=0;i<FragmentList->NumberOfMolecules;i++) {3855 // make up factors to regain total energy of whole molecule3856 FragmentsList[1]->TEList[3*i] = FragmentList->TEList[i]; // bond energy is 1 * whole3857 FragmentsList[1]->TEList[3*i+1] = -FragmentList->TEList[i]; // - 1. * left part3858 FragmentsList[1]->TEList[3*i+2] = -FragmentList->TEList[i]; // - 1. * right part3859 3860 // shift the pointer on whole molecule to new list in order to avoid that this molecule is deleted on deconstructing FragmentList3861 FragmentsList[1]->ListOfMolecules[3*i] = FragmentList->ListOfMolecules[i];3862 *out << Verbose(2) << "shifting whole fragment pointer for fragment " << FragmentList->ListOfMolecules[i] << " -> " << FragmentsList[1]->ListOfMolecules[3*i] << "." << endl;3863 // create bond matrix and count bonds3864 *out << Verbose(2) << "Updating bond list for fragment " << i << " [" << FragmentList << "]: " << FragmentList->ListOfMolecules[i] << endl;3865 // create list of bonds per atom for this fragment (atoms were counted above)3866 FragmentsList[1]->ListOfMolecules[3*i]->CreateListOfBondsPerAtom(out);3867 3868 *out << Verbose(0) << "Getting left & right fragments for fragment " << i << "." << endl;3869 // the bond around which the fragment has been setup is always the first by construction (bond partners are first added atoms)3870 Bond = FragmentsList[1]->ListOfMolecules[3*i]->first->next; // is the bond between atom 0 and another in the middle3871 FragmentsList[1]->ListOfMolecules[3*i]->FragmentMoleculeByBond(out, Bond, &(FragmentsList[1]->ListOfMolecules[3*i+1]), &(FragmentsList[1]->ListOfMolecules[3*i+2]), configuration->GetIsAngstroem(), CutCyclic);3872 if ((FragmentsList[1]->ListOfMolecules[3*i+1] == NULL) || (FragmentsList[1]->ListOfMolecules[3*i+2] == NULL)) {3873 *out << Verbose(2) << "Left and/or Right Fragment is NULL!" << endl;3874 } else {3875 *out << Verbose(3) << "Left Fragment is " << FragmentsList[1]->ListOfMolecules[3*i+1] << ": " << endl;3876 FragmentsList[1]->ListOfMolecules[3*i+1]->Output(out);3877 *out << Verbose(3) << "Right Fragment is " << FragmentsList[1]->ListOfMolecules[3*i+2] << ": " << endl;3878 FragmentsList[1]->ListOfMolecules[3*i+2]->Output(out);3879 *out << endl;3880 }3881 // remove in old list, so that memory for this molecule is not free'd on final delete of this list3882 FragmentList->ListOfMolecules[i] = NULL;3883 }3884 *out << Verbose(0) << "End of Separating Fragments into Bond pieces." << endl;3885 delete(FragmentList);3886 FragmentList = NULL;3887 3888 // combine atomic and bond list3889 FragmentList = new MoleculeListClass(FragmentsList[0]->NumberOfMolecules + FragmentsList[1]->NumberOfMolecules, AtomCount);3890 Num = 0;3891 for(int i=0;i<2;i++) {3892 for(int j=0;j<FragmentsList[i]->NumberOfMolecules;j++) {3893 // transfer molecule3894 FragmentList->ListOfMolecules[Num] = FragmentsList[i]->ListOfMolecules[j];3895 FragmentsList[i]->ListOfMolecules[j] = NULL;3896 // transfer TE factor3897 FragmentList->TEList[Num] = FragmentsList[i]->TEList[j];3898 Num++;3899 }3900 delete(FragmentsList[i]);3901 FragmentsList[i] = NULL;3902 }3903 *out << Verbose(2) << "Memory cleanup and return with filled list." << endl;3904 Free((void **)&FragmentsList, "molecule::FragmentBottomUp: **FragmentsList");3905 3906 // reducing list3907 FragmentList->ReduceToUniqueList(out, &cell_size[0], BondDistance);3908 3909 // write configs for all fragements (are written in FragmentMolecule)3910 // free FragmentList3911 *out << Verbose(0) << "End of FragmentBottomUp." << endl;3912 return FragmentList;3913 };3914 3915 3612 3916 3613 /** Comparision function for GSL heapsort on distances in two molecules.
Note:
See TracChangeset
for help on using the changeset viewer.