Changeset c75363 for molecuilder/src/moleculelist.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/moleculelist.cpp
re936b3 rc75363 21 21 MoleculeListClass::MoleculeListClass(int NumMolecules, int NumAtoms) 22 22 { 23 TEList = (double*) Malloc(sizeof(double)*NumMolecules, "MoleculeListClass:MoleculeListClass: *TEList");24 23 ListOfMolecules = (molecule **) Malloc(sizeof(molecule *)*NumMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 25 for (int i=0;i<NumMolecules;i++) { 26 TEList[i] = 0.; 24 for (int i=0;i<NumMolecules;i++) 27 25 ListOfMolecules[i] = NULL; 28 }29 26 NumberOfMolecules = NumMolecules; 30 27 NumberOfTopAtoms = NumAtoms; … … 36 33 MoleculeListClass::~MoleculeListClass() 37 34 { 38 cout << Verbose(3) << this << ": Freeing ListOfMolcules and TEList." << endl;35 cout << Verbose(3) << this << ": Freeing ListOfMolcules." << endl; 39 36 for (int i=0;i<NumberOfMolecules;i++) { 40 37 if (ListOfMolecules[i] != NULL) { // if NULL don't free … … 46 43 cout << Verbose(4) << "Freeing ListOfMolecules." << endl; 47 44 Free((void **)&ListOfMolecules, "MoleculeListClass:MoleculeListClass: **ListOfMolecules"); 48 cout << Verbose(4) << "Freeing TEList." << endl; 49 Free((void **)&TEList, "MoleculeListClass:MoleculeListClass: *TEList"); 50 }; 51 45 }; 46 47 /** Compare whether two molecules are equal. 48 * \param *a molecule one 49 * \param *n molecule two 50 * \return lexical value (-1, 0, +1) 51 */ 52 52 int MolCompare(const void *a, const void *b) 53 53 { … … 122 122 }; 123 123 124 /** Returns an allocated index list which fragment should remain and which are doubly appearing.125 * Again, we use linked cell however not with \a threshold which in most cases is too small and would126 * generate too many cells, but a too be specified \a celldistance which should e.g. be chosen in127 * the magnitude of the typical bond distance. In order to avoid so far the need of a vector list,128 * we simply use the molecule structure and the vector sitting in the atom structure.129 * \param *out output stream for debugging130 * \param **MapList empty but allocated(MoleculeListClass::NumberOfMolecules), containing on return mapping of for which equal molecule which atoms corresponds to which one (needed for ForceFactors)131 * \param threshold threshold value for molecule::IsEqualToWithinThreshold()132 * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric)133 * \param celldistance needed for linked-cell technique to find possible equals134 * \return allocated index list with \a Num entries.135 */136 int * MoleculeListClass::GetMappingToUniqueFragments(ofstream *out, double threshold, double *cell_size, double celldistance)137 {138 int j, UniqueIndex, HighestNumber;139 //int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index;140 int Counter;141 //molecule **CellList;142 int *MapList = NULL;143 size_t *SortMap = NULL;144 //atom *Walker = NULL, *OtherWalker = NULL;145 //molecule *LinkedCellContainer = new molecule(NULL); // container for all the center of gravities stored as atoms146 147 /// Allocated MapList with range NumberOfMolecules.148 MapList = (int *) Malloc(sizeof(int)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");149 SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *MapList");150 for (j=0;j<NumberOfMolecules;j++) {151 if (ListOfMolecules[j] == NULL)152 cerr << "ERROR: Molecule " << j << " is NULL!" << endl;153 //else154 //cerr << "ERROR: Molecule " << j << " is " << ListOfMolecules[j] << " with count " << ListOfMolecules[j]->AtomCount << "." << endl;155 MapList[j] = -1;156 SortMap[j] = 0;157 }158 *out << Verbose(1) << "Get mapping to unique fragments with " << NumberOfMolecules << " fragments total." << endl;159 160 // sort the list with heapsort according to sort function161 gsl_heapsort_index(SortMap, ListOfMolecules, NumberOfMolecules, sizeof(molecule *), MolCompare);162 // check next neighbours and remap163 Counter = 0;164 MapList[SortMap[0]] = Counter++;165 for(int i=1;i<NumberOfMolecules;i++) {166 if (MolCompare(&ListOfMolecules[SortMap[i]], &ListOfMolecules[SortMap[i-1]]) == 0)167 MapList[SortMap[i]] = MapList[SortMap[i-1]];168 else169 MapList[SortMap[i]] = Counter++;170 }171 Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");172 173 *out << Verbose(2) << "Map: ";174 for(int i=0;i<NumberOfMolecules;i++)175 *out << MapList[i] << " ";176 *out << endl;177 178 // bring MapList indices into an ascending order179 HighestNumber = Counter;180 *out << Verbose(3) << "HighestNumber: " << HighestNumber << "." << endl;181 SortMap = (size_t *) Malloc(sizeof(size_t)*NumberOfMolecules, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");182 for(int i=0;i<NumberOfMolecules;i++)183 SortMap[i] = HighestNumber; // is the first number that will not appear anymore in list184 UniqueIndex = 0;185 for(int i=0;i<NumberOfMolecules;i++)186 if (MapList[i] != -1) {187 if ((unsigned int)SortMap[MapList[i]] == (unsigned int)HighestNumber)188 SortMap[MapList[i]] = UniqueIndex++;189 MapList[i] = SortMap[MapList[i]];190 } else {191 MapList[i] = -1;192 }193 *out << Verbose(2) << "Ascending Map: ";194 for(int i=0;i<NumberOfMolecules;i++)195 *out << MapList[i] << " ";196 *out << endl;197 Free((void **)&SortMap, "MoleculeListClass::GetMappingToUniqueFragments: *SortMap");198 199 /// Return the constructed list.200 return MapList;201 };202 203 204 /** Takes a list of molecules and returns the list with doubles removed.205 * Checks by using molecule::IsEqualToWithinThreshold() whether fragments within the list206 * are actually doubles. If not, the pointer are copied to a new list, if so,207 * they are dropped. The new list is then copied back to the reallocated \a **FragmentList208 * and the new number of elements therein returned.209 * \param *out output stream for debugging210 * \param *Map mapping of which index goes on which (from molecule::GetMappingToUniqueFragments())211 * \return number of molecules in the new realloacted **FragmentList212 */213 int MoleculeListClass::ReduceFragmentToUniqueOnes(ofstream *out, int *Map)214 {215 *out << Verbose(2) << "Begin of ReduceFragmentToUniqueOnes" << endl;216 /// Allocate temporary lists of size \a Num.217 molecule **NewMolList = (molecule **) Malloc(sizeof(molecule *)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: NewList");218 double *NewTEList = (double *) Malloc(sizeof(double)*NumberOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList");219 for(int i=0;i<NumberOfMolecules;i++) {220 NewTEList[i] = 0;221 NewMolList[i] = NULL;222 }223 int ReducedNum = 0, j;224 *out << Verbose(3) << "Reducing TE and Forces lists." << endl;225 for(int i=0;i<NumberOfMolecules;i++) { /// Count new reduced number of molecules ...226 //*out << Verbose(4) << i << "th TE Value " << " goes to " << Map[i] << ": " << TEList[i] << "." << endl;227 NewTEList[Map[i]] += TEList[i];228 if (Map[i] == i) { /// ... by checking if Map[i] != i, then Fragment[i] is double of Fragment[Map[i]].229 *out << Verbose(4) << "Copying molecule " << i << " as it is unique so far ... " << ListOfMolecules[i]<< endl;230 NewMolList[ReducedNum++] = ListOfMolecules[i]; /// ..., whilst copying each value to temporary list, ...231 } else { // else free molecule cause it appears doubly232 *out << Verbose(4) << "Removing molecule " << i << "." << endl;233 delete(ListOfMolecules[i]);234 ListOfMolecules[i] = NULL;235 }236 }237 /// Reallocate \a **FragmentList ...238 *out << Verbose(3) << "Reallocating to Unique Fragments:" << endl;239 if ((ReducedNum != 0) && (TEList != 0)) {240 // factor list241 *out << Verbose(4) << "Reallocating TEList [" << TEList << "] to " << ReducedNum << endl;242 TEList = (double *) ReAlloc(TEList, sizeof(double)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: *TEList");243 244 *out << Verbose(4) << "Copying values to new list: " << endl;245 j = 0; // is ReducedNum index246 for(int i=0;i<NumberOfMolecules;i++) {/// copy value from temporary to return list247 if (Map[i] == i) {248 //if (fabs(NewTEList[i]) > MYEPSILON) { // this is a good check also, if TEList[i] = 0 then fragment cancels and may be dropped!249 TEList[j] = NewTEList[i];250 *out << Verbose(5) << "TE [i" << i << "<->j" << j << "]:" << NewTEList[i] << "->" << TEList[j];251 j++;252 }253 *out << endl;254 }255 if (j != ReducedNum)256 *out << "Panic: j " << j << " != ReducedNum " << ReducedNum << "." << endl;257 258 259 // molecule list260 *out << Verbose(4) << "Reallocating ListOfMolecules ... " << endl;261 ListOfMolecules = (molecule **) ReAlloc(ListOfMolecules, sizeof(molecule *)*ReducedNum, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");262 NumberOfMolecules = ReducedNum;263 /// ... and copy the reduced number back264 *out << Verbose(5) << "Transfering to ListOfMolecules ... ";265 for(int i=0;i<ReducedNum;i++) {266 ListOfMolecules[i] = NewMolList[i];267 *out << NewMolList[i] << " -> " << ListOfMolecules[i] << "\t";268 }269 *out << endl;270 271 272 } else {273 Free((void **)&ListOfMolecules, "MoleculeListClass::ReduceFragmentToUniqueOnes: ListOfMolecules");274 NumberOfMolecules = ReducedNum;275 *out << Verbose(3) << "ReducedNum is " << ReducedNum << ", Number of Molecules is " << NumberOfMolecules << "." << endl;276 }277 // free all the lists again278 *out << Verbose(3) << "Freeing temporary lists." << endl;279 Free((void **)&NewTEList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewTEList"); /// free temporary list again280 Free((void **)&NewMolList, "MoleculeListClass::ReduceFragmentToUniqueOnes: *NewMolList");281 *out << Verbose(2) << "End of ReduceFragmentToUniqueOnes" << endl;282 return(ReducedNum);283 };284 285 124 /** Simple output of the pointers in ListOfMolecules. 286 125 * \param *out output stream … … 295 134 296 135 /** Writes a config file for each molecule in the given \a **FragmentList. 297 * Note that molecules with a TEList factor of 0 are not stored! 298 * \param *prefix prefix for the file name 136 * \param *out output stream for debugging 299 137 * \param *configuration standard configuration to attach atoms in fragment molecule to. 300 138 * \param *SortIndex Index to map from the BFS labeling to the sequence how of Ion_Type in the config 301 139 * \return true - success (each file was written), false - something went wrong. 302 140 */ 303 bool MoleculeListClass::OutputConfigForListOfFragments( char *prefix, config *configuration, int *SortIndex)141 bool MoleculeListClass::OutputConfigForListOfFragments(ofstream *out, config *configuration, int *SortIndex) 304 142 { 305 143 ofstream outputFragment; … … 310 148 atom *Walker = NULL; 311 149 vector BoxDimension; 312 char TEFilename[MAXSTRINGSIZE];313 150 char *FragmentNumber; 314 151 int FragmentCounter = 0; 315 152 ofstream output; 316 element *runner = NULL;317 153 318 154 // store the fragments as config and as xyz 319 155 for(int i=0;i<NumberOfMolecules;i++) { 320 //if (TEList[i] != 0) { 321 strcpy(PathBackup, configuration->configpath); 322 323 // scan all atoms in the current molecule for their fathers and write each vertex index to forces file 324 325 // correct periodic 326 ListOfMolecules[i]->ScanForPeriodicCorrection((ofstream *)&cout); 327 328 // output xyz file 329 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++); 330 sprintf(FragmentName, "%s/%s%s.conf.xyz", PathBackup, prefix, FragmentNumber); 331 outputFragment.open(FragmentName, ios::out); 332 cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ..."; 333 if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)) 334 cout << " done." << endl; 335 else 336 cout << " failed." << endl; 337 result = result && intermediateResult; 338 outputFragment.close(); 339 outputFragment.clear(); 340 341 cout << Verbose(2) << "Contained atoms: "; 342 Walker = ListOfMolecules[i]->start; 343 while (Walker->next != ListOfMolecules[i]->end) { 344 Walker = Walker->next; 345 cout << Walker->Name << " "; 346 } 347 cout << endl; 348 // prepare output of config file 349 sprintf(FragmentName, "%s/%s%s.conf", PathBackup, prefix, FragmentNumber); 350 outputFragment.open(FragmentName, ios::out); 351 strcpy(PathBackup, configuration->configpath); 352 sprintf(FragmentName, "%s/%s%s/", PathBackup, prefix, FragmentNumber); 353 354 // center on edge 355 ListOfMolecules[i]->CenterEdge((ofstream *)&cout, &BoxDimension); 356 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary 357 int j = -1; 358 for (int k=0;k<3;k++) { 359 j += k+1; 360 BoxDimension.x[k] = 5.; 361 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.; 362 } 363 ListOfMolecules[i]->Translate(&BoxDimension); 364 365 // also calculate necessary orbitals 366 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment 367 ListOfMolecules[i]->CalculateOrbitals(*configuration); 368 369 // change path in config 370 configuration->SetDefaultPath(FragmentName); 371 cout << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ..."; 372 if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i])) 373 cout << " done." << endl; 374 else 375 cout << " failed." << endl; 376 // restore old config 377 configuration->SetDefaultPath(PathBackup); 378 379 result = result && intermediateResult; 380 outputFragment.close(); 381 outputFragment.clear(); 382 Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); 383 } 384 385 strcpy(PathBackup, configuration->configpath); 386 // open file for the total energy factor 387 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, TEFACTORSFILE); 388 output.open(TEFilename, ios::out); 389 // output TEList (later to file AtomicTEList.dat) 390 cout << Verbose(2) << "Saving " << prefix << " energy factors ..."; 391 //cout << Verbose(1) << "Final ATEList: "; 392 //less output << prefix << "TE\t"; 393 for(int i=0;i<NumberOfMolecules;i++) { 394 //cout << TEList[i] << "\t"; 395 //if (TEList[i] != 0) 396 output << TEList[i] << "\t"; 397 } 398 //cout << endl; 399 output << endl; 156 // save default path as it is changed for each fragment 157 strcpy(PathBackup, configuration->GetDefaultPath()); 158 159 // correct periodic 160 ListOfMolecules[i]->ScanForPeriodicCorrection(out); 161 162 // output xyz file 163 FragmentNumber = FixedDigitNumber(NumberOfMolecules, FragmentCounter++); 164 sprintf(FragmentName, "%s/%s%s.conf.xyz", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 165 outputFragment.open(FragmentName, ios::out); 166 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as XYZ ..."; 167 if (intermediateResult = ListOfMolecules[i]->OutputXYZ(&outputFragment)) 168 *out << " done." << endl; 169 else 170 *out << " failed." << endl; 171 result = result && intermediateResult; 172 outputFragment.close(); 173 outputFragment.clear(); 174 175 *out << Verbose(2) << "Contained atoms: "; 176 Walker = ListOfMolecules[i]->start; 177 while (Walker->next != ListOfMolecules[i]->end) { 178 Walker = Walker->next; 179 *out << Walker->Name << " "; 180 } 181 *out << endl; 182 // prepare output of config file 183 sprintf(FragmentName, "%s/%s%s.conf", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 184 outputFragment.open(FragmentName, ios::out); 185 strcpy(PathBackup, configuration->configpath); 186 sprintf(FragmentName, "%s/%s%s/", configuration->configpath, FRAGMENTPREFIX, FragmentNumber); 187 188 // center on edge 189 ListOfMolecules[i]->CenterEdge(out, &BoxDimension); 190 ListOfMolecules[i]->SetBoxDimension(&BoxDimension); // update Box of atoms by boundary 191 int j = -1; 192 for (int k=0;k<3;k++) { 193 j += k+1; 194 BoxDimension.x[k] = 5.; 195 ListOfMolecules[i]->cell_size[j] += BoxDimension.x[k]*2.; 196 } 197 ListOfMolecules[i]->Translate(&BoxDimension); 198 199 // also calculate necessary orbitals 200 ListOfMolecules[i]->CountElements(); // this is a bugfix, atoms should should actually be added correctly to this fragment 201 ListOfMolecules[i]->CalculateOrbitals(*configuration); 202 203 // change path in config 204 configuration->SetDefaultPath(FragmentName); 205 *out << Verbose(2) << "Saving bond fragment No. " << FragmentNumber << " as config ..."; 206 if (intermediateResult = configuration->Save(&outputFragment, ListOfMolecules[i]->elemente, ListOfMolecules[i])) 207 *out << " done." << endl; 208 else 209 *out << " failed." << endl; 210 // restore old config 211 configuration->SetDefaultPath(PathBackup); 212 213 result = result && intermediateResult; 214 outputFragment.close(); 215 outputFragment.clear(); 216 Free((void **)&FragmentNumber, "MoleculeListClass::OutputConfigForListOfFragments: *FragmentNumber"); 217 } 218 219 // open KeySet file 220 sprintf(FragmentName, "%s/%s%s", configuration->configpath, FRAGMENTPREFIX , KEYSETFILE); 221 output.open(FragmentName, ios::out); 222 *out << Verbose(2) << "Saving " << FRAGMENTPREFIX << " key sets of each subgraph ..."; 223 for(int j=0;j<NumberOfMolecules;j++) { 224 Walker = ListOfMolecules[j]->start; 225 while(Walker->next != ListOfMolecules[j]->end) { 226 Walker = Walker->next; 227 #ifdef ADDHYDROGEN 228 if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index 229 #else 230 if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index 231 #endif 232 output << Walker->GetTrueFather()->nr << "\t"; 233 #ifdef ADDHYDROGEN 234 else // otherwise a -1 to indicate an added saturation hydrogen 235 output << "-1\t"; 236 #endif 237 } 238 output << endl; 239 } 400 240 output.close(); 401 cout << " done." << endl; 402 403 // open file for the force factors 404 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, FORCESFILE); 405 output.open(TEFilename, ios::out); 406 //cout << Verbose(1) << "Final AtomicForcesList: "; 407 cout << Verbose(2) << "Saving " << prefix << " force factors ..."; 408 //output << prefix << "Forces" << endl; 409 for(int j=0;j<NumberOfMolecules;j++) { 410 //if (TEList[j] != 0) { 411 runner = ListOfMolecules[j]->elemente->start; 412 while (runner->next != ListOfMolecules[j]->elemente->end) { // go through every element 413 runner = runner->next; 414 if (ListOfMolecules[j]->ElementsInMolecule[runner->Z]) { // if this element got atoms 415 Walker = ListOfMolecules[j]->start; 416 while (Walker->next != ListOfMolecules[j]->end) { // go through every atom of this element 417 Walker = Walker->next; 418 if (Walker->type->Z == runner->Z) { 419 if ((Walker->GetTrueFather() != NULL) && (Walker->GetTrueFather() != Walker)) {// if there is a real father, prints its index 420 //cout << "Walker is " << *Walker << " with true father " << *( Walker->GetTrueFather()) << ", its number " << Walker->GetTrueFather()->nr << " and index " << SortIndex[Walker->GetTrueFather()->nr] << "." << endl; 421 output << SortIndex[Walker->GetTrueFather()->nr] << "\t"; 422 } else // otherwise a -1 to indicate an added saturation hydrogen 423 output << "-1\t"; 424 } 425 } 426 } 427 } 428 //cout << endl << endl; 429 output << endl; 430 } 431 output.close(); 432 cout << " done." << endl; 433 434 // open KeySet file 435 sprintf(TEFilename, "%s/%s%s", PathBackup, prefix, "KeySets.dat"); 436 output.open(TEFilename, ios::out); 437 cout << Verbose(2) << "Saving " << prefix << " key sets of each subgraph ..."; 438 for(int j=0;j<NumberOfMolecules;j++) { 439 //if (TEList[j] != 0) { 440 Walker = ListOfMolecules[j]->start; 441 while(Walker->next != ListOfMolecules[j]->end) { 442 Walker = Walker->next; 443 #ifdef ADDHYDROGEN 444 if ((Walker->GetTrueFather() != NULL) && (Walker->type->Z != 1)) // if there is a real father, prints its index 445 #else 446 if ((Walker->GetTrueFather() != NULL)) // if there is a real father, prints its index 447 #endif 448 output << Walker->GetTrueFather()->nr << "\t"; 449 #ifdef ADDHYDROGEN 450 else // otherwise a -1 to indicate an added saturation hydrogen 451 output << "-1\t"; 452 #endif 453 } 454 //cout << endl << endl; 455 output << endl; 456 } 457 output.close(); 458 cout << " done." << endl; 241 *out << " done." << endl; 459 242 460 243 // printing final number 461 cout << "Final number of fragments: " << FragmentCounter << "." << endl;244 *out << "Final number of fragments: " << FragmentCounter << "." << endl; 462 245 463 246 return result; 464 247 }; 465 466 /** Reduce the list of molecules to unique pieces.467 * molecule::IsEqualToWithinThreshold() is used by GetMappingToUniqueFragments() to provide a mapping for468 * ReduceFragmentToUniqueOnes().469 * \param *out output stream for debugging470 * \param cell_size 6 entries specifying the unit cell vectors (matrix is symmetric) for getting the map471 * \param celldistance needed for linked-cell technique when getting the map472 */473 void MoleculeListClass::ReduceToUniqueList(ofstream *out, double *cell_size, double celldistance)474 {475 int *ReduceMapping = NULL;476 477 *out << Verbose(0) << "Begin of ReduceToUniqueList." << endl;478 // again, check whether there are equal fragments by ReduceToUniqueOnes479 *out << Verbose(1) << "Get reduce mapping." << endl;480 ReduceMapping = GetMappingToUniqueFragments(out, 0.05, cell_size, celldistance);481 *out << Verbose(1) << "MapList: ";482 for(int i=0;i<NumberOfMolecules;i++)483 *out << ReduceMapping[i] << " ";484 *out << endl << endl;485 *out << Verbose(1) << "Apply reduce mapping." << endl;486 ReduceFragmentToUniqueOnes(out, ReduceMapping);487 Free((void **)&ReduceMapping, "MoleculeListClass::FragmentTopDown: *ReduceMapping"); // free map after reduce488 *out << Verbose(1) << "Number of Fragments after Reducing is " << NumberOfMolecules << "." << endl;489 *out << Verbose(0) << "End of ReduceToUniqueList." << endl;490 };491 492 /** Fragments a molecule and resulting pieces recursively until the number of bonds493 * Here the idea is similar to the FragmentBottomUp() approach, only that we split up the molecule494 * bond per bond into left and right fragments and this recursively also with each yielded495 * fragment until there is no fragment with continuous number of bonds greater than \a BondDegree.496 * are below the given \a BondDegree.497 * \param *out output stream for debugging498 * \param BondDegree maximum number of continuous bonds in a fragment499 * \param bonddistance typical bond distance500 * \param *configuration configuration for writing config files for each fragment501 * \param CutCyclic cut cyclic bonds (saturate with hydrogen) or add502 * \return pointer to MoleculeListClass with all the fragments or NULL if something went wrong.503 * \todo so far we volontarily mix up the above BondDegree definition and molecule::NoNonBonds504 *505 * \bug FragmentTopDown does not work right now due to NULL being given as cell_size to ReduceToUniqueOnes()506 */507 MoleculeListClass * MoleculeListClass::FragmentTopDown(ofstream *out, int BondDegree, double bonddistance, config *configuration, enum CutCyclicBond CutCyclic)508 {509 int Num, No, Cyclic, NoBonds;510 MoleculeListClass *ReturnList = NULL;511 MoleculeListClass **FragmentsList = NULL;512 molecule *CurrentMolecule = NULL;513 bond *Binder = NULL;514 515 *out << Verbose(0) << "Begin of FragmentTopDown:" << this << "." << endl;516 Num = 0;517 FragmentsList = (MoleculeListClass **) Malloc(sizeof(MoleculeListClass *)*NumberOfMolecules, "MoleculeListClass::FragmentTopDown: **FragmentsList");518 // fragment each molecule into its own MoleculeListClass519 for(int i=0;i<NumberOfMolecules;i++) {520 CurrentMolecule = ListOfMolecules[i];521 CurrentMolecule->CountAtoms(out);522 Cyclic = CurrentMolecule->CountCyclicBonds(out);523 NoBonds =524 #ifdef ADDHYDROGEN525 CurrentMolecule->NoNonBonds526 #else527 CurrentMolecule->BondCount528 #endif529 - ((CutCyclic == KeepBond) ? Cyclic : 0);530 // check if NoNonBonds < BondDegree, then don't split any further: Here, correct for greatest continuous bond length!531 *out << Verbose(0) << "Checking on Number of true Bonds " << NoBonds << " (i.e. no -H, if chosen no cyclic) greater than " << BondDegree << "." << endl;532 if (NoBonds > BondDegree) {533 //cerr << Verbose(1) << "TopDown Level of Molecule " << CurrentMolecule << ": " << (CurrentMolecule->NoNonBonds - BondDegree) << "." << endl;534 *out << Verbose(1) << "Breaking up molecule " << i << " in fragment list." << endl;535 CurrentMolecule->CreateListOfBondsPerAtom(out);536 // Get atomic fragments for the list537 *out << Verbose(1) << "Getting Atomic fragments for molecule " << i << "." << endl;538 MoleculeListClass *AtomicFragments = CurrentMolecule->GetAtomicFragments(out, NumberOfTopAtoms, configuration->GetIsAngstroem(), TEList[i]/(1. - NoBonds), CutCyclic);539 540 // build the atomic part of the list of molecules541 *out << Verbose(1) << "Putting atomic fragment into list of molecules." << endl;542 543 // cutting cyclic bonds yields only a single fragment, not two as non-cyclic!544 No = (CutCyclic == KeepBond) ? ((545 #ifdef ADDHYDROGEN546 CurrentMolecule->NoNonBonds - Cyclic)*2) : CurrentMolecule->NoNonBonds*2 - Cyclic;547 #else548 CurrentMolecule->BondCount - Cyclic)*2) : CurrentMolecule->BondCount*2 - Cyclic;549 #endif550 551 if (AtomicFragments != NULL) {552 ReturnList = new MoleculeListClass(No+AtomicFragments->NumberOfMolecules, NumberOfTopAtoms);553 for (int j=0;j<AtomicFragments->NumberOfMolecules;j++) { // shift all Atomic Fragments into this one here554 ReturnList->ListOfMolecules[j+No] = AtomicFragments->ListOfMolecules[j];555 AtomicFragments->ListOfMolecules[j] = NULL;556 ReturnList->ListOfMolecules[j+No]->NoNonBonds = 0;557 ReturnList->ListOfMolecules[j+No]->NoNonHydrogen = 1;558 ReturnList->TEList[j+No] = AtomicFragments->TEList[j];559 }560 *out << Verbose(3) << "Freeing Atomic memory" << endl;561 delete(AtomicFragments);562 AtomicFragments = NULL;563 } else {564 *out << Verbose(2) << "AtomicFragments is NULL, filling list with whole molecule only." << endl;565 ReturnList = new MoleculeListClass(No, NumberOfTopAtoms);566 }567 568 // build the side pieces part of the list of molecules569 *out << Verbose(1) << "Building side piece fragments and putting into list of molecules." << endl;570 No = 0;571 Binder = CurrentMolecule->first;572 while(Binder->next != CurrentMolecule->last) {573 Binder = Binder->next;574 #ifdef ADDHYDROGEN575 if (Binder->HydrogenBond == 0)576 #endif577 if ((CutCyclic == SaturateBond) || (!Binder->Cyclic)) {578 // split each bond into left and right side piece579 if (Binder->Cyclic) {580 molecule *dummy = NULL; // we lazily hand FragmentMoleculeByBond() a dummy as second fragment and ...581 *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, CYCLIC bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into a single pieces." << endl;582 CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(dummy), configuration->GetIsAngstroem(), CutCyclic);583 delete(dummy); // ... free the dummy which is due to the cyclic bond the exacy same fragment584 *out << Verbose(1) << "Single fragment is " << ReturnList->ListOfMolecules[No] << "." << endl;585 586 // write down the necessary TE-summation in order to regain TE of whole molecule587 *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;588 #ifdef ADDHYDROGEN589 ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->NoNonBonds);590 #else591 ReturnList->TEList[No] = -TEList[i]/(1. -CurrentMolecule->BondCount);592 #endif593 } else {594 *out << Verbose(1) << "Breaking up " << Binder->nr << "th and " << No << "th non-hydrogen, non-cyclic bond " << *Binder << " of molecule " << i << " [" << CurrentMolecule << "] into left and right side pieces." << endl;595 CurrentMolecule->FragmentMoleculeByBond(out, Binder, &(ReturnList->ListOfMolecules[No]), &(ReturnList->ListOfMolecules[No+1]), configuration->GetIsAngstroem(), CutCyclic);596 *out << Verbose(1) << "Left Fragment is " << ReturnList->ListOfMolecules[No] << ", right Fragment is " << ReturnList->ListOfMolecules[No+1] << "." << endl;597 598 // write down the necessary TE-summation in order to regain TE of whole molecule599 *out << Verbose(2) << "Creating TEList for Fragment " << i << " of Bond " << No << "." << endl;600 ReturnList->TEList[No] = -TEList[i]/(1. - NoBonds);601 ReturnList->TEList[No+1] = -TEList[i]/(1. - NoBonds);602 }603 No += ((Binder->Cyclic) ? 1 : 2);604 }605 }606 607 // Reduce this list608 ReturnList->ReduceToUniqueList(out, NULL, bonddistance);609 610 // recurse and receive List611 *out << Verbose(1) << "Calling TopDown " << ReturnList<< " with filled list: ";612 ReturnList->Output(out);613 FragmentsList[i] = ReturnList->FragmentTopDown(out, BondDegree, bonddistance, configuration, CutCyclic);614 *out << Verbose(1) << "Returning from TopDown " << ReturnList<< " with filled list: ";615 ReturnList->Output(out);616 617 // remove list after we're done618 *out << Verbose(2) << "Removing caller list." << endl;619 delete(ReturnList);620 ReturnList = NULL;621 622 } else { // create a list with only a single molecule inside, transfer everything from "this" list to return list623 *out << Verbose(1) << "Not breaking up molecule " << i << " in fragment list." << endl;624 FragmentsList[i] = new MoleculeListClass(1, NumberOfTopAtoms);625 FragmentsList[i]->ListOfMolecules[0] = ListOfMolecules[i];626 ListOfMolecules[i] = NULL;627 FragmentsList[i]->TEList[0] = TEList[i];628 }629 Num += FragmentsList[i]->NumberOfMolecules;630 }631 632 // now, we have a list of MoleculeListClasses: combine all fragments list into one single list633 *out << Verbose(2) << "Combining to a list of " << Num << " molecules and Memory cleanup of old list of lists." << endl;634 ReturnList = new MoleculeListClass(Num, NumberOfTopAtoms);635 No = 0;636 for(int i=0;i<NumberOfMolecules;i++) {637 for(int j=0;j<FragmentsList[i]->NumberOfMolecules;j++) {638 // transfer molecule639 ReturnList->ListOfMolecules[No] = FragmentsList[i]->ListOfMolecules[j];640 FragmentsList[i]->ListOfMolecules[j] = NULL;641 // transfer TE factor642 ReturnList->TEList[No] = FragmentsList[i]->TEList[j];643 No++;644 }645 delete(FragmentsList[i]);646 FragmentsList[i] = NULL;647 }648 Free((void **)&FragmentsList, "MoleculeListClass::FragmentTopDown: **FragmentsList");649 650 // Reduce the list to unique fragments651 ReturnList->ReduceToUniqueList(out, NULL, bonddistance);652 653 // return pointer to list654 *out << Verbose(0) << "Return with filled list: ";655 ReturnList->Output(out);656 657 *out << Verbose(0) << "End of FragmentTopDown:" << this << "." << endl;658 return (ReturnList);659 };660 248 661 249 /******************************************* Class MoleculeLeafClass ************************************************/
Note:
See TracChangeset
for help on using the changeset viewer.