Changeset 5034e1 for src/molecule_fragmentation.cpp
- Timestamp:
- Oct 12, 2009, 12:10:43 PM (16 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- d2943b
- Parents:
- 4a7776a
- git-author:
- Frederik Heber <heber@…> (10/12/09 12:04:44)
- git-committer:
- Frederik Heber <heber@…> (10/12/09 12:10:43)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/molecule_fragmentation.cpp
r4a7776a r5034e1 50 50 * \return true - at least one valid atom id parsed, false - CurrentSet is empty 51 51 */ 52 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)52 bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet) 53 53 { 54 54 stringstream line; … … 59 59 while (!line.eof()) { 60 60 line >> AtomNr; 61 if ( (AtomNr >= 0) && (AtomNr < AtomCount)) {61 if (AtomNr >= 0) { 62 62 CurrentSet.insert(AtomNr); // insert at end, hence in same order as in file! 63 63 status++; … … 82 82 * \return true - parsing successfully, false - failure on parsing (FragmentList will be NULL) 83 83 */ 84 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)84 bool ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList) 85 85 { 86 86 bool status = true; … … 89 89 GraphTestPair testGraphInsert; 90 90 int NumberOfFragments = 0; 91 double TEFactor;92 91 char *filename = Malloc<char>(MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename"); 93 92 … … 124 123 } 125 124 125 return status; 126 }; 127 128 /** Parses the TE factors file and fills \a *FragmentList from the known molecule structure. 129 * -# Scans TEFactors file and sets the TEFactor of each key set in the temporary graph accordingly 130 * \param *out output stream for debugging 131 * \param *path path to file 132 * \param *FragmentList graph whose nodes's TE factors are set on return 133 * \return true - parsing successfully, false - failure on parsing 134 */ 135 bool ParseTEFactorsFile(ofstream *out, char *path, Graph *FragmentList) 136 { 137 bool status = true; 138 ifstream InputFile; 139 stringstream line; 140 GraphTestPair testGraphInsert; 141 int NumberOfFragments = 0; 142 double TEFactor; 143 char *filename = Malloc<char>(MAXSTRINGSIZE, "molecule::ParseTEFactorsFile - filename"); 144 145 if (FragmentList == NULL) { // check list pointer 146 FragmentList = new Graph; 147 } 148 126 149 // 2nd pass: open TEFactors file and read 127 150 *out << Verbose(1) << "Parsing the TEFactors file ... " << endl; … … 155 178 }; 156 179 157 /** Stores key sets and TEFactors to file.158 * \param *out output stream for debugging 159 * \param KeySetList Graph with Keysets and factors180 /** Stores key sets to file. 181 * \param *out output stream for debugging 182 * \param KeySetList Graph with Keysets 160 183 * \param *path path to file 161 184 * \return true - file written successfully, false - writing failed 162 185 */ 163 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)186 bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path) 164 187 { 165 188 ofstream output; … … 190 213 output.close(); 191 214 output.clear(); 215 216 return status; 217 }; 218 219 220 /** Stores TEFactors to file. 221 * \param *out output stream for debugging 222 * \param KeySetList Graph with factors 223 * \param *path path to file 224 * \return true - file written successfully, false - writing failed 225 */ 226 bool StoreTEFactorsFile(ofstream *out, Graph &KeySetList, char *path) 227 { 228 ofstream output; 229 bool status = true; 230 string line; 192 231 193 232 // open TEFactors file … … 211 250 }; 212 251 252 /** For a given graph, sorts KeySets into a (index, keyset) map. 253 * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase 254 * \return map from index to keyset 255 */ 256 map<int,KeySet> * GraphToIndexedKeySet(Graph *GlobalKeySetList) 257 { 258 map<int,KeySet> *IndexKeySetList = new map<int,KeySet>; 259 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 260 IndexKeySetList->insert( pair<int,KeySet>(runner->second.first,runner->first) ); 261 } 262 return IndexKeySetList; 263 }; 264 265 /** Inserts a (\a No, \a value) pair into the list, overwriting present one. 266 * Note if values are equal, No will decided on which is first 267 * \param *out output stream for debugging 268 * \param &AdaptiveCriteriaList list to insert into 269 * \param &IndexedKeySetList list to find key set for a given index \a No 270 * \param FragOrder current bond order of fragment 271 * \param No index of keyset 272 * \param value energy value 273 */ 274 void InsertIntoAdaptiveCriteriaList(ofstream *out, map<int, pair<double,int> > *AdaptiveCriteriaList, map<int,KeySet> &IndexKeySetList, int FragOrder, int No, double Value) 275 { 276 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 277 if (marker != IndexKeySetList.end()) { // if found 278 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes them not equal without changing anything actually 279 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 280 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList->insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 281 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 282 if (!InsertedElement.second) { // this root is already present 283 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 284 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 285 { // if value is smaller, update value and order 286 (*PresentItem).second.first = fabs(Value); 287 (*PresentItem).second.second = FragOrder; 288 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 289 } else { 290 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 291 } 292 } else { 293 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 294 } 295 } else { 296 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 297 } 298 }; 299 300 /** Scans the adaptive order file and insert (index, value) into map. 301 * \param *out output stream for debugging 302 * \param *path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative) 303 * \param &IndexedKeySetList list to find key set for a given index \a No 304 * \return adaptive criteria list from file 305 */ 306 map<int, pair<double,int> > * ScanAdaptiveFileIntoMap(ofstream *out, char *path, map<int,KeySet> &IndexKeySetList) 307 { 308 map<int, pair<double,int> > *AdaptiveCriteriaList = new map<int, pair<double,int> >; 309 int No = 0, FragOrder = 0; 310 double Value = 0.; 311 char *buffer = Malloc<char>(MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 312 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 313 ifstream InputFile(buffer, ios::in); 314 315 if (CountLinesinFile(InputFile) > 0) { 316 // each line represents a fragment root (Atom::nr) id and its energy contribution 317 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 318 InputFile.getline(buffer, MAXSTRINGSIZE); 319 while(!InputFile.eof()) { 320 InputFile.getline(buffer, MAXSTRINGSIZE); 321 if (strlen(buffer) > 2) { 322 //*out << Verbose(2) << "Scanning: " << buffer << endl; 323 stringstream line(buffer); 324 line >> FragOrder; 325 line >> ws >> No; 326 line >> ws >> Value; // skip time entry 327 line >> ws >> Value; 328 No -= 1; // indices start at 1 in file, not 0 329 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 330 331 // clean the list of those entries that have been superceded by higher order terms already 332 InsertIntoAdaptiveCriteriaList(out, AdaptiveCriteriaList, IndexKeySetList, FragOrder, No, Value); 333 } 334 } 335 // close and done 336 InputFile.close(); 337 InputFile.clear(); 338 } 339 Free(&buffer); 340 341 return AdaptiveCriteriaList; 342 }; 343 344 /** Maps adaptive criteria list back onto (Value, (Root Nr., Order)) 345 * (i.e. sorted by value to pick the highest ones) 346 * \param *out output stream for debugging 347 * \param &AdaptiveCriteriaList list to insert into 348 * \param *mol molecule with atoms 349 * \return remapped list 350 */ 351 map<double, pair<int,int> > * ReMapAdaptiveCriteriaListToValue(ofstream *out, map<int, pair<double,int> > *AdaptiveCriteriaList, molecule *mol) 352 { 353 atom *Walker = mol->start; 354 map<double, pair<int,int> > *FinalRootCandidates = new map<double, pair<int,int> > ; 355 *out << Verbose(1) << "Root candidate list is: " << endl; 356 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList->begin(); runner != AdaptiveCriteriaList->end(); runner++) { 357 Walker = mol->FindAtom((*runner).first); 358 if (Walker != NULL) { 359 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 360 if (!Walker->MaxOrder) { 361 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 362 FinalRootCandidates->insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 363 } else { 364 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 365 } 366 } else { 367 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 368 } 369 } 370 return FinalRootCandidates; 371 }; 372 373 /** Marks all candidate sites for update if below adaptive threshold. 374 * Picks a given number of highest values and set *AtomMask to true. 375 * \param *out output stream for debugging 376 * \param *AtomMask defines true/false per global Atom::nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively 377 * \param FinalRootCandidates list candidates to check 378 * \param Order desired order 379 * \param *mol molecule with atoms 380 * \return true - if update is necessary, false - not 381 */ 382 bool MarkUpdateCandidates(ofstream *out, bool *AtomMask, map<double, pair<int,int> > &FinalRootCandidates, int Order, molecule *mol) 383 { 384 atom *Walker = mol->start; 385 int No = -1; 386 bool status = false; 387 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 388 No = (*runner).second.first; 389 Walker = mol->FindAtom(No); 390 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 391 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 392 AtomMask[No] = true; 393 status = true; 394 //} else 395 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 396 } 397 return status; 398 }; 399 400 /** print atom mask for debugging. 401 * \param *out output stream for debugging 402 * \param *AtomMask defines true/false per global Atom::nr to mask in/out each nuclear site, used to activate given number of site to increment order adaptively 403 * \param AtomCount number of entries in \a *AtomMask 404 */ 405 void PrintAtomMask(ofstream *out, bool *AtomMask, int AtomCount) 406 { 407 *out << " "; 408 for(int i=0;i<AtomCount;i++) 409 *out << (i % 10); 410 *out << endl << "Atom mask is: "; 411 for(int i=0;i<AtomCount;i++) 412 *out << (AtomMask[i] ? "t" : "f"); 413 *out << endl; 414 }; 213 415 214 416 /** Checks whether the OrderAtSite is still below \a Order at some site. … … 225 427 atom *Walker = start; 226 428 bool status = false; 227 ifstream InputFile;228 429 229 430 // initialize mask list … … 234 435 if (AtomMask[AtomCount] == true) // break after one step 235 436 return false; 437 438 // transmorph graph keyset list into indexed KeySetList 439 if (GlobalKeySetList == NULL) { 440 cout << Verbose(1) << "ERROR: Given global key set list (graph) is NULL!" << endl; 441 return false; 442 } 443 map<int,KeySet> *IndexKeySetList = GraphToIndexedKeySet(GlobalKeySetList); 444 236 445 // parse the EnergyPerFragment file 237 char *buffer = Malloc<char>(MAXSTRINGSIZE, "molecule::CheckOrderAtSite: *buffer"); 238 sprintf(buffer, "%s/%s%s.dat", path, FRAGMENTPREFIX, ENERGYPERFRAGMENT); 239 InputFile.open(buffer, ios::in); 240 if ((InputFile != NULL) && (GlobalKeySetList != NULL)) { 241 // transmorph graph keyset list into indexed KeySetList 242 map<int,KeySet> IndexKeySetList; 243 for(Graph::iterator runner = GlobalKeySetList->begin(); runner != GlobalKeySetList->end(); runner++) { 244 IndexKeySetList.insert( pair<int,KeySet>(runner->second.first,runner->first) ); 245 } 246 int lines = 0; 247 // count the number of lines, i.e. the number of fragments 248 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 249 InputFile.getline(buffer, MAXSTRINGSIZE); 250 while(!InputFile.eof()) { 251 InputFile.getline(buffer, MAXSTRINGSIZE); 252 lines++; 253 } 254 //*out << Verbose(2) << "Scanned " << lines-1 << " lines." << endl; // one endline too much 255 InputFile.clear(); 256 InputFile.seekg(ios::beg); 257 map<int, pair<double,int> > AdaptiveCriteriaList; // (Root No., (Value, Order)) ! 258 int No, FragOrder; 259 double Value; 260 // each line represents a fragment root (Atom::nr) id and its energy contribution 261 InputFile.getline(buffer, MAXSTRINGSIZE); // skip comment lines 262 InputFile.getline(buffer, MAXSTRINGSIZE); 263 while(!InputFile.eof()) { 264 InputFile.getline(buffer, MAXSTRINGSIZE); 265 if (strlen(buffer) > 2) { 266 //*out << Verbose(2) << "Scanning: " << buffer << endl; 267 stringstream line(buffer); 268 line >> FragOrder; 269 line >> ws >> No; 270 line >> ws >> Value; // skip time entry 271 line >> ws >> Value; 272 No -= 1; // indices start at 1 in file, not 0 273 //*out << Verbose(2) << " - yields (" << No << "," << Value << ", " << FragOrder << ")" << endl; 274 275 // clean the list of those entries that have been superceded by higher order terms already 276 map<int,KeySet>::iterator marker = IndexKeySetList.find(No); // find keyset to Frag No. 277 if (marker != IndexKeySetList.end()) { // if found 278 Value *= 1 + MYEPSILON*(*((*marker).second.begin())); // in case of equal energies this makes em not equal without changing anything actually 279 // as the smallest number in each set has always been the root (we use global id to keep the doubles away), seek smallest and insert into AtomMask 280 pair <map<int, pair<double,int> >::iterator, bool> InsertedElement = AdaptiveCriteriaList.insert( make_pair(*((*marker).second.begin()), pair<double,int>( fabs(Value), FragOrder) )); 281 map<int, pair<double,int> >::iterator PresentItem = InsertedElement.first; 282 if (!InsertedElement.second) { // this root is already present 283 if ((*PresentItem).second.second < FragOrder) // if order there is lower, update entry with higher-order term 284 //if ((*PresentItem).second.first < (*runner).first) // as higher-order terms are not always better, we skip this part (which would always include this site into adaptive increase) 285 { // if value is smaller, update value and order 286 (*PresentItem).second.first = fabs(Value); 287 (*PresentItem).second.second = FragOrder; 288 *out << Verbose(2) << "Updated element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 289 } else { 290 *out << Verbose(2) << "Did not update element " << (*PresentItem).first << " as " << FragOrder << " is less than or equal to " << (*PresentItem).second.second << "." << endl; 291 } 292 } else { 293 *out << Verbose(2) << "Inserted element (" << (*PresentItem).first << ",[" << (*PresentItem).second.first << "," << (*PresentItem).second.second << "])." << endl; 294 } 295 } else { 296 *out << Verbose(1) << "No Fragment under No. " << No << "found." << endl; 297 } 298 } 299 } 300 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 301 map<double, pair<int,int> > FinalRootCandidates; 302 *out << Verbose(1) << "Root candidate list is: " << endl; 303 for(map<int, pair<double,int> >::iterator runner = AdaptiveCriteriaList.begin(); runner != AdaptiveCriteriaList.end(); runner++) { 304 Walker = FindAtom((*runner).first); 305 if (Walker != NULL) { 306 //if ((*runner).second.second >= Walker->AdaptiveOrder) { // only insert if this is an "active" root site for the current order 307 if (!Walker->MaxOrder) { 308 *out << Verbose(2) << "(" << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "])" << endl; 309 FinalRootCandidates.insert( make_pair( (*runner).second.first, pair<int,int>((*runner).first, (*runner).second.second) ) ); 310 } else { 311 *out << Verbose(2) << "Excluding (" << *Walker << ", " << (*runner).first << ",[" << (*runner).second.first << "," << (*runner).second.second << "]), as it has reached its maximum order." << endl; 312 } 313 } else { 314 cerr << "Atom No. " << (*runner).second.first << " was not found in this molecule." << endl; 315 } 316 } 317 // pick the ones still below threshold and mark as to be adaptively updated 318 for(map<double, pair<int,int> >::iterator runner = FinalRootCandidates.upper_bound(pow(10.,Order)); runner != FinalRootCandidates.end(); runner++) { 319 No = (*runner).second.first; 320 Walker = FindAtom(No); 321 //if (Walker->AdaptiveOrder < MinimumRingSize[Walker->nr]) { 322 *out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", setting entry " << No << " of Atom mask to true." << endl; 323 AtomMask[No] = true; 324 status = true; 325 //} else 326 //*out << Verbose(2) << "Root " << No << " is still above threshold (10^{" << Order <<"}: " << runner->first << ", however MinimumRingSize of " << MinimumRingSize[Walker->nr] << " does not allow further adaptive increase." << endl; 327 } 328 // close and done 329 InputFile.close(); 330 InputFile.clear(); 331 } else { 332 cerr << "Unable to parse " << buffer << " file, incrementing all." << endl; 446 map<int, pair<double,int> > *AdaptiveCriteriaList = ScanAdaptiveFileIntoMap(out, path, *IndexKeySetList); // (Root No., (Value, Order)) ! 447 if (AdaptiveCriteriaList->empty()) { 448 cerr << "Unable to parse file, incrementing all." << endl; 333 449 while (Walker->next != end) { 334 450 Walker = Walker->next; … … 342 458 } 343 459 } 344 Free(&buffer); 345 // pick a given number of highest values and set AtomMask 460 // then map back onto (Value, (Root Nr., Order)) (i.e. sorted by value to pick the highest ones) 461 map<double, pair<int,int> > *FinalRootCandidates = ReMapAdaptiveCriteriaListToValue(out, AdaptiveCriteriaList, this); 462 463 // pick the ones still below threshold and mark as to be adaptively updated 464 MarkUpdateCandidates(out, AtomMask, *FinalRootCandidates, Order, this); 465 466 Free(&IndexKeySetList); 467 Free(&AdaptiveCriteriaList); 468 Free(&FinalRootCandidates); 346 469 } else { // global increase of Bond Order 347 470 while (Walker->next != end) { … … 367 490 } 368 491 369 // print atom mask for debugging 370 *out << " "; 371 for(int i=0;i<AtomCount;i++) 372 *out << (i % 10); 373 *out << endl << "Atom mask is: "; 374 for(int i=0;i<AtomCount;i++) 375 *out << (AtomMask[i] ? "t" : "f"); 376 *out << endl; 492 PrintAtomMask(out, AtomMask, AtomCount); // for debugging 377 493 378 494 return status; … … 383 499 * \param *&SortIndex Mapping array of size molecule::AtomCount 384 500 * \return true - success, false - failure of SortIndex alloc 385 * \todo do we really need this still as the IonType may appear in any order due to recent changes386 501 */ 387 502 bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex) 388 503 { 389 element *runner = elemente->start;390 int AtomNo = 0;391 atom *Walker = NULL;392 393 504 if (SortIndex != NULL) { 394 505 *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl; 395 506 return false; 396 507 } 397 SortIndex = Malloc<int>(AtomCount, "molecule:: FragmentMolecule: *SortIndex");508 SortIndex = Malloc<int>(AtomCount, "molecule::CreateMappingLabelsToConfigSequence: *SortIndex"); 398 509 for(int i=AtomCount;i--;) 399 510 SortIndex[i] = -1; 400 while (runner->next != elemente->end) { // go through every element 401 runner = runner->next; 402 if (ElementsInMolecule[runner->Z]) { // if this element got atoms 403 Walker = start; 404 while (Walker->next != end) { // go through every atom of this element 405 Walker = Walker->next; 406 if (Walker->type->Z == runner->Z) // if this atom fits to element 407 SortIndex[Walker->nr] = AtomNo++; 408 } 409 } 410 } 511 512 int AtomNo = 0; 513 SetIndexedArrayForEachAtomTo( SortIndex, &atom::nr, &IncrementalAbsoluteValue, AtomNo ); 514 411 515 return true; 412 516 }; … … 631 735 *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl; 632 736 if (file != NULL) { 633 atom *Walker = start; 634 while (Walker->next != end) { 635 Walker = Walker->next; 636 file << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << endl; 637 *out << Verbose(2) << "Storing: " << Walker->nr << "\t" << (int)Walker->AdaptiveOrder << "\t" << (int)Walker->MaxOrder << "." << endl; 638 } 737 ActOnAllAtoms( &atom::OutputOrder, &file ); 639 738 file.close(); 640 739 *out << Verbose(1) << "done." << endl; … … 683 782 } 684 783 } 685 atom *Walker = start;686 while (Walker->next != end) { // fill into atom classes687 Walker = Walker->next;688 Walker->AdaptiveOrder = OrderArray[Walker->nr];689 Walker->MaxOrder = MaxArray[Walker->nr];690 *out << Verbose(2) << *Walker << " gets order " << (int)Walker->AdaptiveOrder << " and is " << (!Walker->MaxOrder ? "not " : " ") << "maxed." << endl;691 }692 784 file.close(); 785 786 // set atom values 787 SetAtomValueToIndexedArray( OrderArray, &atom::nr, &atom::AdaptiveOrder ); 788 SetAtomValueToIndexedArray( MaxArray, &atom::nr, &atom::MaxOrder ); 789 693 790 *out << Verbose(1) << "done." << endl; 694 791 status = true; … … 732 829 }; 733 830 734 /** Stores a fragment from \a KeySet into \a molecule. 735 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 736 * molecule and adds missing hydrogen where bonds were cut. 737 * \param *out output stream for debugging messages 831 /** Initializes some value for putting fragment of \a *mol into \a *Leaf. 832 * \param *mol total molecule 833 * \param *Leaf fragment molecule 738 834 * \param &Leaflet pointer to KeySet structure 739 * \param IsAngstroem whether we have Ansgtroem or bohrradius 740 * \return pointer to constructed molecule 741 */ 742 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 743 { 744 atom *Runner = NULL, *FatherOfRunner = NULL, *OtherFather = NULL; 745 atom **SonList = Malloc<atom*>(AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 746 molecule *Leaf = new molecule(elemente); 747 bool LonelyFlag = false; 748 int size; 749 750 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 751 752 Leaf->BondDistance = BondDistance; 835 * \param **SonList list which atom of \a *Leaf is a son of which atom in \a *mol 836 * \return number of atoms in fragment 837 */ 838 int StoreFragmentFromKeySet_Init(molecule *mol, molecule *Leaf, KeySet &Leaflet, atom **SonList) 839 { 840 atom *FatherOfRunner = NULL; 841 842 Leaf->BondDistance = mol->BondDistance; 753 843 for(int i=NDIM*2;i--;) 754 Leaf->cell_size[i] = cell_size[i];844 Leaf->cell_size[i] = mol->cell_size[i]; 755 845 756 846 // initialise SonList (indicates when we need to replace a bond with hydrogen instead) 757 for(int i= AtomCount;i--;)847 for(int i=mol->AtomCount;i--;) 758 848 SonList[i] = NULL; 759 849 760 850 // first create the minimal set of atoms from the KeySet 761 size = 0;851 int size = 0; 762 852 for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) { 763 FatherOfRunner = FindAtom((*runner)); // find the id853 FatherOfRunner = mol->FindAtom((*runner)); // find the id 764 854 SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner); 765 855 size++; 766 856 } 767 768 // create the bonds between all: Make it an induced subgraph and add hydrogen 769 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 770 Runner = Leaf->start; 857 return size; 858 }; 859 860 /** Creates an induced subgraph out of a fragmental key set, adding bonds and hydrogens (if treated specially). 861 * \param *out output stream for debugging messages 862 * \param *mol total molecule 863 * \param *Leaf fragment molecule 864 * \param IsAngstroem whether we have Ansgtroem or bohrradius 865 * \param **SonList list which atom of \a *Leaf is a son of which atom in \a *mol 866 */ 867 void CreateInducedSubgraphOfFragment(ofstream *out, molecule *mol, molecule *Leaf, atom **SonList, bool IsAngstroem) 868 { 869 bool LonelyFlag = false; 870 atom *OtherFather = NULL; 871 atom *FatherOfRunner = NULL; 872 Leaf->CountAtoms(out); 873 874 atom *Runner = Leaf->start; 771 875 while (Runner->next != Leaf->end) { 772 876 Runner = Runner->next; … … 775 879 if (SonList[FatherOfRunner->nr] != NULL) { // check if this, our father, is present in list 776 880 // create all bonds 777 for (int i=0;i< NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father778 OtherFather = ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner);881 for (int i=0;i<mol->NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father 882 OtherFather = mol->ListOfBondsPerAtom[FatherOfRunner->nr][i]->GetOtherAtom(FatherOfRunner); 779 883 // *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather; 780 884 if (SonList[OtherFather->nr] != NULL) { … … 783 887 // *out << Verbose(3) << "Adding Bond: "; 784 888 // *out << 785 Leaf->AddBond(Runner, SonList[OtherFather->nr], ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree);889 Leaf->AddBond(Runner, SonList[OtherFather->nr], mol->ListOfBondsPerAtom[FatherOfRunner->nr][i]->BondDegree); 786 890 // *out << "." << endl; 787 891 //NumBonds[Runner->nr]++; … … 794 898 #ifdef ADDHYDROGEN 795 899 //*out << Verbose(3) << "Adding Hydrogen to " << Runner->Name << " and a bond in between." << endl; 796 if(!Leaf->AddHydrogenReplacementAtom(out, ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, ListOfBondsPerAtom[FatherOfRunner->nr],NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem))900 if(!Leaf->AddHydrogenReplacementAtom(out, mol->ListOfBondsPerAtom[FatherOfRunner->nr][i], Runner, FatherOfRunner, OtherFather, mol->ListOfBondsPerAtom[FatherOfRunner->nr],mol->NumberOfBondsPerAtom[FatherOfRunner->nr], IsAngstroem)) 797 901 exit(1); 798 902 #endif … … 803 907 *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl; 804 908 } 805 if ((LonelyFlag) && ( size> 1)) {909 if ((LonelyFlag) && (Leaf->AtomCount > 1)) { 806 910 *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl; 807 911 } … … 811 915 #endif 812 916 } 917 }; 918 919 /** Stores a fragment from \a KeySet into \a molecule. 920 * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete 921 * molecule and adds missing hydrogen where bonds were cut. 922 * \param *out output stream for debugging messages 923 * \param &Leaflet pointer to KeySet structure 924 * \param IsAngstroem whether we have Ansgtroem or bohrradius 925 * \return pointer to constructed molecule 926 */ 927 molecule * molecule::StoreFragmentFromKeySet(ofstream *out, KeySet &Leaflet, bool IsAngstroem) 928 { 929 atom **SonList = Malloc<atom*>(AtomCount, "molecule::StoreFragmentFromStack: **SonList"); 930 molecule *Leaf = new molecule(elemente); 931 932 // *out << Verbose(1) << "Begin of StoreFragmentFromKeyset." << endl; 933 StoreFragmentFromKeySet_Init(this, Leaf, Leaflet, SonList); 934 // create the bonds between all: Make it an induced subgraph and add hydrogen 935 // *out << Verbose(2) << "Creating bonds from father graph (i.e. induced subgraph creation)." << endl; 936 CreateInducedSubgraphOfFragment(out, this, Leaf, SonList, IsAngstroem); 937 813 938 Leaf->CreateListOfBondsPerAtom(out); 814 939 //Leaflet->Leaf->ScanForPeriodicCorrection(out); … … 817 942 return Leaf; 818 943 }; 819 820 /** Creates \a MoleculeListClass of all unique fragments of the \a molecule containing \a Order atoms or vertices.821 * The picture to have in mind is that of a DFS "snake" of a certain length \a Order, i.e. as in the infamous822 * computer game, that winds through the connected graph representing the molecule. Color (white,823 * lightgray, darkgray, black) indicates whether a vertex has been discovered so far or not. Labels will help in824 * creating only unique fragments and not additional ones with vertices simply in different sequence.825 * The Predecessor is always the one that came before in discovering, needed on backstepping. And826 * finally, the ShortestPath is needed for removing vertices from the snake stack during the back-827 * stepping.828 * \param *out output stream for debugging829 * \param Order number of atoms in each fragment830 * \param *configuration configuration for writing config files for each fragment831 * \return List of all unique fragments with \a Order atoms832 */833 /*834 MoleculeListClass * molecule::CreateListOfUniqueFragmentsOfOrder(ofstream *out, int Order, config *configuration)835 {836 atom **PredecessorList = Malloc<atom*>(AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: **PredecessorList");837 int *ShortestPathList = Malloc<int>(AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ShortestPathList");838 int *Labels = Malloc<int>(AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *Labels");839 enum Shading *ColorVertexList = Malloc<enum Shading>(AtomCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorList");840 enum Shading *ColorEdgeList = Malloc<enum Shading>(BondCount, "molecule::CreateListOfUniqueFragmentsOfOrder: *ColorBondList");841 StackClass<atom *> *RootStack = new StackClass<atom *>(AtomCount);842 StackClass<atom *> *TouchedStack = new StackClass<atom *>((int)pow(4,Order)+2); // number of atoms reached from one with maximal 4 bonds plus Root itself843 StackClass<atom *> *SnakeStack = new StackClass<atom *>(Order+1); // equal to Order is not possible, as then the StackClass<atom *> cannot discern between full and empty stack!844 MoleculeLeafClass *Leaflet = NULL, *TempLeaf = NULL;845 MoleculeListClass *FragmentList = NULL;846 atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL, *Removal = NULL;847 bond *Binder = NULL;848 int RunningIndex = 0, FragmentCounter = 0;849 850 *out << Verbose(1) << "Begin of CreateListOfUniqueFragmentsOfOrder." << endl;851 852 // reset parent list853 *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;854 for (int i=0;i<AtomCount;i++) { // reset all atom labels855 // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons856 Labels[i] = -1;857 SonList[i] = NULL;858 PredecessorList[i] = NULL;859 ColorVertexList[i] = white;860 ShortestPathList[i] = -1;861 }862 for (int i=0;i<BondCount;i++)863 ColorEdgeList[i] = white;864 RootStack->ClearStack(); // clearstack and push first atom if exists865 TouchedStack->ClearStack();866 Walker = start->next;867 while ((Walker != end)868 #ifdef ADDHYDROGEN869 && (Walker->type->Z == 1)870 }871 }872 *out << ", SP of " << ShortestPathList[Walker->nr] << " and its color is " << GetColor(ColorVertexList[Walker->nr]) << "." << endl;873 874 // then check the stack for a newly stumbled upon fragment875 if (SnakeStack->ItemCount() == Order) { // is stack full?876 // store the fragment if it is one and get a removal candidate877 Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);878 // remove the candidate if one was found879 if (Removal != NULL) {880 *out << Verbose(2) << "Removing item " << Removal->Name << " with SP of " << ShortestPathList[Removal->nr] << " from snake stack." << endl;881 SnakeStack->RemoveItem(Removal);882 ColorVertexList[Removal->nr] = lightgray; // return back to not on snake stack but explored marking883 if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back884 Walker = PredecessorList[Removal->nr];885 *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;886 }887 }888 } else889 Removal = NULL;890 891 // finally, look for a white neighbour as the next Walker892 Binder = NULL;893 if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) { // don't look, if a new walker has been set above894 *out << Verbose(2) << "Snake has currently " << SnakeStack->ItemCount() << " item(s)." << endl;895 OtherAtom = NULL; // this is actually not needed, every atom has at least one neighbour896 if (ShortestPathList[Walker->nr] < Order) {897 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {898 Binder = ListOfBondsPerAtom[Walker->nr][i];899 *out << Verbose(2) << "Current bond is " << *Binder << ": ";900 OtherAtom = Binder->GetOtherAtom(Walker);901 if ((Labels[OtherAtom->nr] != -1) && (Labels[OtherAtom->nr] < Labels[Root->nr])) { // we don't step up to labels bigger than us902 *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;903 //ColorVertexList[OtherAtom->nr] = lightgray; // mark as explored904 } else { // otherwise check its colour and element905 if (906 (OtherAtom->type->Z != 1) &&907 #endif908 (ColorEdgeList[Binder->nr] == white)) { // skip hydrogen, look for unexplored vertices909 *out << "Moving along " << GetColor(ColorEdgeList[Binder->nr]) << " bond " << Binder << " to " << ((ColorVertexList[OtherAtom->nr] == white) ? "unexplored" : "explored") << " item: " << OtherAtom->Name << "." << endl;910 // i find it currently rather sensible to always set the predecessor in order to find one's way back911 //if (PredecessorList[OtherAtom->nr] == NULL) {912 PredecessorList[OtherAtom->nr] = Walker;913 *out << Verbose(3) << "Setting Predecessor of " << OtherAtom->Name << " to " << PredecessorList[OtherAtom->nr]->Name << "." << endl;914 //} else {915 // *out << Verbose(3) << "Predecessor of " << OtherAtom->Name << " is " << PredecessorList[OtherAtom->nr]->Name << "." << endl;916 //}917 Walker = OtherAtom;918 break;919 } else {920 if (OtherAtom->type->Z == 1)921 *out << "Links to a hydrogen atom." << endl;922 else923 *out << "Bond has not white but " << GetColor(ColorEdgeList[Binder->nr]) << " color." << endl;924 }925 }926 }927 } else { // means we have stepped beyond the horizon: Return!928 Walker = PredecessorList[Walker->nr];929 OtherAtom = Walker;930 *out << Verbose(3) << "We have gone too far, stepping back to " << Walker->Name << "." << endl;931 }932 if (Walker != OtherAtom) { // if no white neighbours anymore, color it black933 *out << Verbose(2) << "Coloring " << Walker->Name << " black." << endl;934 ColorVertexList[Walker->nr] = black;935 Walker = PredecessorList[Walker->nr];936 }937 }938 } while ((Walker != Root) || (ColorVertexList[Root->nr] != black));939 *out << Verbose(2) << "Inner Looping is finished." << endl;940 941 // if we reset all AtomCount atoms, we have again technically O(N^2) ...942 *out << Verbose(2) << "Resetting lists." << endl;943 Walker = NULL;944 Binder = NULL;945 while (!TouchedStack->IsEmpty()) {946 Walker = TouchedStack->PopLast();947 *out << Verbose(3) << "Re-initialising entries of " << *Walker << "." << endl;948 for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++)949 ColorEdgeList[ListOfBondsPerAtom[Walker->nr][i]->nr] = white;950 PredecessorList[Walker->nr] = NULL;951 ColorVertexList[Walker->nr] = white;952 ShortestPathList[Walker->nr] = -1;953 }954 }955 *out << Verbose(1) << "Outer Looping over all vertices is done." << endl;956 957 // copy together958 *out << Verbose(1) << "Copying all fragments into MoleculeList structure." << endl;959 FragmentList = new MoleculeListClass(FragmentCounter, AtomCount);960 RunningIndex = 0;961 while ((Leaflet != NULL) && (RunningIndex < FragmentCounter)) {962 FragmentList->ListOfMolecules[RunningIndex++] = Leaflet->Leaf;963 Leaflet->Leaf = NULL; // prevent molecule from being removed964 TempLeaf = Leaflet;965 Leaflet = Leaflet->previous;966 delete(TempLeaf);967 };968 969 // free memory and exit970 Free(&PredecessorList);971 Free(&ShortestPathList);972 Free(&Labels);973 Free(&ColorVertexList);974 delete(RootStack);975 delete(TouchedStack);976 delete(SnakeStack);977 978 *out << Verbose(1) << "End of CreateListOfUniqueFragmentsOfOrder." << endl;979 return FragmentList;980 };981 */982 944 983 945 /** From a given set of Bond sorted by Shortest Path distance, create all possible fragments of size \a SetDimension.
Note:
See TracChangeset
for help on using the changeset viewer.