Ignore:
Timestamp:
Oct 12, 2009, 12:10:43 PM (16 years ago)
Author:
Frederik Heber <heber@…>
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)
Message:

First half of molecule_fragmentation.cpp refactoring.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecule_fragmentation.cpp

    r4a7776a r5034e1  
    5050 * \return true - at least one valid atom id parsed, false - CurrentSet is empty
    5151 */
    52 bool molecule::ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)
     52bool ScanBufferIntoKeySet(ofstream *out, char *buffer, KeySet &CurrentSet)
    5353{
    5454  stringstream line;
     
    5959  while (!line.eof()) {
    6060    line >> AtomNr;
    61     if ((AtomNr >= 0) && (AtomNr < AtomCount)) {
     61    if (AtomNr >= 0) {
    6262      CurrentSet.insert(AtomNr);  // insert at end, hence in same order as in file!
    6363      status++;
     
    8282 * \return true - parsing successfully, false - failure on parsing (FragmentList will be NULL)
    8383 */
    84 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
     84bool ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
    8585{
    8686  bool status = true;
     
    8989  GraphTestPair testGraphInsert;
    9090  int NumberOfFragments = 0;
    91   double TEFactor;
    9291  char *filename = Malloc<char>(MAXSTRINGSIZE, "molecule::ParseKeySetFile - filename");
    9392
     
    124123  }
    125124
     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 */
     135bool 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
    126149  // 2nd pass: open TEFactors file and read
    127150  *out << Verbose(1) << "Parsing the TEFactors file ... " << endl;
     
    155178};
    156179
    157 /** Stores keysets and TEFactors to file.
    158  * \param *out output stream for debugging
    159  * \param KeySetList Graph with Keysets and factors
     180/** Stores key sets to file.
     181 * \param *out output stream for debugging
     182 * \param KeySetList Graph with Keysets
    160183 * \param *path path to file
    161184 * \return true - file written successfully, false - writing failed
    162185 */
    163 bool molecule::StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)
     186bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path)
    164187{
    165188  ofstream output;
     
    190213  output.close();
    191214  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 */
     226bool StoreTEFactorsFile(ofstream *out, Graph &KeySetList, char *path)
     227{
     228  ofstream output;
     229  bool status =  true;
     230  string line;
    192231
    193232  // open TEFactors file
     
    211250};
    212251
     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 */
     256map<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 */
     274void 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 */
     306map<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 */
     351map<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 */
     382bool 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 */
     405void 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};
    213415
    214416/** Checks whether the OrderAtSite is still below \a Order at some site.
     
    225427  atom *Walker = start;
    226428  bool status = false;
    227   ifstream InputFile;
    228429
    229430  // initialize mask list
     
    234435    if (AtomMask[AtomCount] == true)  // break after one step
    235436      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
    236445    // 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;
    333449      while (Walker->next != end) {
    334450        Walker = Walker->next;
     
    342458      }
    343459    }
    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);
    346469  } else { // global increase of Bond Order
    347470    while (Walker->next != end) {
     
    367490  }
    368491
    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
    377493
    378494  return status;
     
    383499 * \param *&SortIndex Mapping array of size molecule::AtomCount
    384500 * \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 changes
    386501 */
    387502bool molecule::CreateMappingLabelsToConfigSequence(ofstream *out, int *&SortIndex)
    388503{
    389   element *runner = elemente->start;
    390   int AtomNo = 0;
    391   atom *Walker = NULL;
    392 
    393504  if (SortIndex != NULL) {
    394505    *out << Verbose(1) << "SortIndex is " << SortIndex << " and not NULL as expected." << endl;
    395506    return false;
    396507  }
    397   SortIndex = Malloc<int>(AtomCount, "molecule::FragmentMolecule: *SortIndex");
     508  SortIndex = Malloc<int>(AtomCount, "molecule::CreateMappingLabelsToConfigSequence: *SortIndex");
    398509  for(int i=AtomCount;i--;)
    399510    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
    411515  return true;
    412516};
     
    631735  *out << Verbose(1) << "Writing OrderAtSite " << ORDERATSITEFILE << " ... " << endl;
    632736  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 );
    639738    file.close();
    640739    *out << Verbose(1) << "done." << endl;
     
    683782      }
    684783    }
    685     atom *Walker = start;
    686     while (Walker->next != end) { // fill into atom classes
    687       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     }
    692784    file.close();
     785
     786    // set atom values
     787    SetAtomValueToIndexedArray( OrderArray, &atom::nr, &atom::AdaptiveOrder );
     788    SetAtomValueToIndexedArray( MaxArray, &atom::nr, &atom::MaxOrder );
     789
    693790    *out << Verbose(1) << "done." << endl;
    694791    status = true;
     
    732829};
    733830
    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
    738834 * \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 */
     838int StoreFragmentFromKeySet_Init(molecule *mol, molecule *Leaf, KeySet &Leaflet, atom **SonList)
     839{
     840  atom *FatherOfRunner = NULL;
     841
     842  Leaf->BondDistance = mol->BondDistance;
    753843  for(int i=NDIM*2;i--;)
    754     Leaf->cell_size[i] = cell_size[i];
     844    Leaf->cell_size[i] = mol->cell_size[i];
    755845
    756846  // 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--;)
    758848    SonList[i] = NULL;
    759849
    760850  // first create the minimal set of atoms from the KeySet
    761   size = 0;
     851  int size = 0;
    762852  for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
    763     FatherOfRunner = FindAtom((*runner));  // find the id
     853    FatherOfRunner = mol->FindAtom((*runner));  // find the id
    764854    SonList[FatherOfRunner->nr] = Leaf->AddCopyAtom(FatherOfRunner);
    765855    size++;
    766856  }
    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 */
     867void 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;
    771875  while (Runner->next != Leaf->end) {
    772876    Runner = Runner->next;
     
    775879    if (SonList[FatherOfRunner->nr] != NULL)  {  // check if this, our father, is present in list
    776880      // create all bonds
    777       for (int i=0;i<NumberOfBondsPerAtom[FatherOfRunner->nr];i++) { // go through every bond of father
    778         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);
    779883//        *out << Verbose(2) << "Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->nr] << " is bound to " << *OtherFather;
    780884        if (SonList[OtherFather->nr] != NULL) {
     
    783887//            *out << Verbose(3) << "Adding Bond: ";
    784888//            *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);
    786890//            *out << "." << endl;
    787891            //NumBonds[Runner->nr]++;
     
    794898#ifdef ADDHYDROGEN
    795899          //*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))
    797901            exit(1);
    798902#endif
     
    803907      *out << Verbose(0) << "ERROR: Son " << Runner->Name << " has father " << FatherOfRunner->Name << " but its entry in SonList is " << SonList[FatherOfRunner->nr] << "!" << endl;
    804908    }
    805     if ((LonelyFlag) && (size > 1)) {
     909    if ((LonelyFlag) && (Leaf->AtomCount > 1)) {
    806910      *out << Verbose(0) << *Runner << "has got bonds only to hydrogens!" << endl;
    807911    }
     
    811915#endif
    812916  }
     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 */
     927molecule * 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
    813938  Leaf->CreateListOfBondsPerAtom(out);
    814939  //Leaflet->Leaf->ScanForPeriodicCorrection(out);
     
    817942  return Leaf;
    818943};
    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 infamous
    822  * 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 in
    824  * 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. And
    826  * finally, the ShortestPath is needed for removing vertices from the snake stack during the back-
    827  * stepping.
    828  * \param *out output stream for debugging
    829  * \param Order number of atoms in each fragment
    830  * \param *configuration configuration for writing config files for each fragment
    831  * \return List of all unique fragments with \a Order atoms
    832  */
    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 itself
    843   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 list
    853   *out << Verbose(3) << "Resetting labels, parent, predecessor, color and shortest path lists." << endl;
    854   for (int i=0;i<AtomCount;i++) { // reset all atom labels
    855     // initialise each vertex as white with no predecessor, empty queue, color lightgray, not labelled, no sons
    856     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 exists
    865   TouchedStack->ClearStack();
    866   Walker = start->next;
    867   while ((Walker != end)
    868 #ifdef ADDHYDROGEN
    869    && (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 fragment
    875       if (SnakeStack->ItemCount() == Order) { // is stack full?
    876         // store the fragment if it is one and get a removal candidate
    877         Removal = StoreFragmentFromStack(out, Root, Walker, Leaflet, SnakeStack, ShortestPathList, SonList, Labels, &FragmentCounter, configuration);
    878         // remove the candidate if one was found
    879         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 marking
    883           if (Walker == Removal) { // if the current atom is to be removed, we also have to take a step back
    884             Walker = PredecessorList[Removal->nr];
    885             *out << Verbose(2) << "Stepping back to " << Walker->Name << "." << endl;
    886           }
    887         }
    888       } else
    889         Removal = NULL;
    890 
    891       // finally, look for a white neighbour as the next Walker
    892       Binder = NULL;
    893       if ((Removal == NULL) || (Walker != PredecessorList[Removal->nr])) {  // don't look, if a new walker has been set above
    894         *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 neighbour
    896         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 us
    902               *out << "Label " << Labels[OtherAtom->nr] << " is smaller than Root's " << Labels[Root->nr] << "." << endl;
    903               //ColorVertexList[OtherAtom->nr] = lightgray;    // mark as explored
    904             } else { // otherwise check its colour and element
    905               if (
    906               (OtherAtom->type->Z != 1) &&
    907 #endif
    908                     (ColorEdgeList[Binder->nr] == white)) {  // skip hydrogen, look for unexplored vertices
    909                 *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 back
    911                 //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                 else
    923                   *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 black
    933           *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 together
    958   *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 removed
    964     TempLeaf = Leaflet;
    965     Leaflet = Leaflet->previous;
    966     delete(TempLeaf);
    967   };
    968 
    969   // free memory and exit
    970   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 */
    982944
    983945/** 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.