Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Fragmentation/Fragmentation.cpp

    r94d5ac6 r3aa8a5  
    4646#include "Element/periodentafel.hpp"
    4747#include "Fragmentation/AdaptivityMap.hpp"
     48#include "Fragmentation/AtomMask.hpp"
    4849#include "Fragmentation/fragmentation_helpers.hpp"
    4950#include "Fragmentation/Graph.hpp"
     51#include "Fragmentation/helpers.hpp"
    5052#include "Fragmentation/KeySet.hpp"
    5153#include "Fragmentation/PowerSetGenerator.hpp"
    5254#include "Fragmentation/UniqueFragments.hpp"
    5355#include "Graph/BondGraph.hpp"
    54 #include "Graph/CheckAgainstAdjacencyFile.hpp"
     56#include "Graph/AdjacencyList.hpp"
     57#include "Graph/ListOfLocalAtoms.hpp"
    5558#include "molecule.hpp"
    56 #include "MoleculeLeafClass.hpp"
    57 #include "MoleculeListClass.hpp"
    58 #include "Parser/FormatParserStorage.hpp"
    5959#include "World.hpp"
    6060
     
    6363 *
    6464 * \param _mol molecule for internal use (looking up atoms)
     65 * \param _FileChecker instance contains adjacency parsed from elsewhere
    6566 * \param _saturation whether to treat hydrogen special and saturate dangling bonds or not
    6667 */
    67 Fragmentation::Fragmentation(molecule *_mol, const enum HydrogenSaturation _saturation) :
     68Fragmentation::Fragmentation(molecule *_mol, AdjacencyList &_FileChecker, const enum HydrogenSaturation _saturation) :
    6869  mol(_mol),
    69   saturation(_saturation)
     70  saturation(_saturation),
     71  FileChecker(_FileChecker)
    7072{}
    7173
     
    8991 * of vertex indices: Global always means the index in "this" molecule, whereas local refers to the molecule or
    9092 * subgraph in the MoleculeListClass.
     93 * \param atomids atomic ids (local to Fragmentation::mol) to fragment, used in AtomMask
    9194 * \param Order up to how many neighbouring bonds a fragment contains in BondOrderScheme::BottumUp scheme
    9295 * \param prefix prefix string for every fragment file name (may include path)
     
    9497 * \return 1 - continue, 2 - stop (no fragmentation occured)
    9598 */
    96 int Fragmentation::FragmentMolecule(int Order, std::string prefix, DepthFirstSearchAnalysis &DFS)
    97 {
    98   MoleculeListClass *BondFragments = NULL;
    99   int FragmentCounter;
    100   MoleculeLeafClass *MolecularWalker = NULL;
    101   MoleculeLeafClass *Subgraphs = NULL;      // list of subgraphs from DFS analysis
    102   fstream File;
    103   bool FragmentationToDo = true;
     99int Fragmentation::FragmentMolecule(const std::vector<atomId_t> &atomids, int Order, std::string prefix, DepthFirstSearchAnalysis &DFS)
     100{
     101  std::fstream File;
    104102  bool CheckOrder = false;
    105   Graph **FragmentList = NULL;
    106   Graph TotalGraph;     // graph with all keysets however local numbers
    107103  int TotalNumberOfKeySets = 0;
    108   atom ***ListOfLocalAtoms = NULL;
    109   bool *AtomMask = NULL;
    110 
    111   LOG(0, endl);
     104
     105  LOG(0, std::endl);
    112106  switch (saturation) {
    113107    case DoSaturate:
     
    123117
    124118  // ++++++++++++++++++++++++++++ INITIAL STUFF: Bond structure analysis, file parsing, ... ++++++++++++++++++++++++++++++++++++++++++
     119  bool FragmentationToDo = true;
    125120
    126121  // ===== 1. Check whether bond structure is same as stored in files ====
     
    128123  // === compare it with adjacency file ===
    129124  {
    130     std::ifstream File;
    131     std::string filename;
    132     filename = prefix + ADJACENCYFILE;
    133     File.open(filename.c_str(), ios::out);
    134     LOG(1, "Looking at bond structure stored in adjacency file and comparing to present one ... ");
    135 
    136     CheckAgainstAdjacencyFile FileChecker(World::getInstance().beginAtomSelection(), World::getInstance().endAtomSelection());
    137     FragmentationToDo = FragmentationToDo && FileChecker(File);
    138   }
    139 
    140   // === reset bond degree and perform CorrectBondDegree ===
    141   for(World::MoleculeIterator iter = World::getInstance().getMoleculeIter();
    142       iter != World::getInstance().moleculeEnd();
    143       ++iter) {
    144     // correct bond degree
    145     World::AtomComposite Set = (*iter)->getAtomSet();
    146     World::getInstance().getBondGraph()->CorrectBondDegree(Set);
    147   }
    148 
    149   // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
    150   // NOTE: We assume here that DFS has been performed and molecule structure is current.
    151   Subgraphs = DFS.getMoleculeStructure();
     125    const std::vector<atomId_t> globalids = getGlobalIdsFromLocalIds(*mol, atomids);
     126    AdjacencyList WorldAdjacency(globalids);
     127    FragmentationToDo = FragmentationToDo && (FileChecker > WorldAdjacency);
     128  }
     129
     130  // ===== 2. create AtomMask that takes Saturation condition into account
     131  AtomMask_t AtomMask(atomids);
     132  for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
     133    // remove in hydrogen and we do saturate
     134    if ((saturation == DoSaturate) && ((*iter)->getType()->getAtomicNumber() == 1)) // skip hydrogen
     135      AtomMask.setFalse((*iter)->getNr());
     136  }
    152137
    153138  // ===== 3. if structure still valid, parse key set file and others =====
     
    156141
    157142  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
    158   FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(prefix);
     143  FragmentationToDo = FragmentationToDo && ParseOrderAtSiteFromFile(atomids, prefix);
    159144
    160145  // =================================== Begin of FRAGMENTATION ===============================
    161146  // ===== 6a. assign each keyset to its respective subgraph =====
    162   const int MolCount = World::getInstance().numMolecules();
    163   ListOfLocalAtoms = new atom **[MolCount];
    164   for (int i=0;i<MolCount;i++)
    165     ListOfLocalAtoms[i] = NULL;
    166   FragmentCounter = 0;
    167   Subgraphs->next->AssignKeySetsToFragment(mol, &ParsedFragmentList, ListOfLocalAtoms, FragmentList, FragmentCounter, true);
    168   delete[](ListOfLocalAtoms);
     147  ListOfLocalAtoms_t ListOfLocalAtoms;
     148  Graph FragmentList;
     149  AssignKeySetsToFragment(ParsedFragmentList, ListOfLocalAtoms, FragmentList, true);
    169150
    170151  // ===== 6b. prepare and go into the adaptive (Order<0), single-step (Order==0) or incremental (Order>0) cycle
    171   KeyStack *RootStack = new KeyStack[Subgraphs->next->Count()];
    172   AtomMask = new bool[mol->getAtomCount()+1];
    173   AtomMask[mol->getAtomCount()] = false;
     152  KeyStack RootStack;
    174153  FragmentationToDo = false;  // if CheckOrderAtSite just ones recommends fragmentation, we will save fragments afterwards
    175   while ((CheckOrder = CheckOrderAtSite(AtomMask, &ParsedFragmentList, Order, prefix))) {
     154  bool LoopDoneAlready = false;
     155  while ((CheckOrder = CheckOrderAtSite(AtomMask, ParsedFragmentList, Order, prefix, LoopDoneAlready))) {
    176156    FragmentationToDo = FragmentationToDo || CheckOrder;
    177     AtomMask[mol->getAtomCount()] = true;   // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
     157    LoopDoneAlready = true;   // last plus one entry is used as marker that we have been through this loop once already in CheckOrderAtSite()
    178158    // ===== 6b. fill RootStack for each subgraph (second adaptivity check) =====
    179     Subgraphs->next->FillRootStackForSubgraphs(RootStack, AtomMask, (FragmentCounter = 0), saturation);
    180 
    181     // ===== 7. fill the bond fragment list =====
    182     FragmentCounter = 0;
    183     MolecularWalker = Subgraphs;
    184     while (MolecularWalker->next != NULL) {
    185       MolecularWalker = MolecularWalker->next;
    186       LOG(1, "Fragmenting subgraph " << MolecularWalker << ".");
    187       if (MolecularWalker->Leaf->hasBondStructure()) {
    188         // call BOSSANOVA method
    189         LOG(0, endl << " ========== BOND ENERGY of subgraph " << FragmentCounter << " ========================= ");
    190         FragmentBOSSANOVA(MolecularWalker->Leaf, FragmentList[FragmentCounter], RootStack[FragmentCounter]);
    191       } else {
    192         ELOG(1, "Subgraph " << MolecularWalker << " has no atoms!");
    193       }
    194       FragmentCounter++;  // next fragment list
    195     }
     159    FillRootStackForSubgraphs(RootStack, AtomMask);
     160
     161    // call BOSSANOVA method
     162    FragmentBOSSANOVA(mol, FragmentList, RootStack);
    196163  }
    197164  LOG(2, "CheckOrder is " << CheckOrder << ".");
    198   delete[](RootStack);
    199   delete[](AtomMask);
    200165
    201166  // ==================================== End of FRAGMENTATION ============================================
    202167
    203168  // ===== 8a. translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
    204   Subgraphs->next->TranslateIndicesToGlobalIDs(FragmentList, (FragmentCounter = 0), TotalNumberOfKeySets, TotalGraph);
    205 
    206   // free subgraph memory again
    207   FragmentCounter = 0;
    208   while (Subgraphs != NULL) {
    209     // remove entry in fragment list
    210     // remove subgraph fragment
    211     MolecularWalker = Subgraphs->next;
    212     Subgraphs->Leaf = NULL;
    213     delete(Subgraphs);
    214     Subgraphs = MolecularWalker;
    215   }
    216   // free fragment list
    217   for (int i=0; i< FragmentCounter; ++i )
    218     delete(FragmentList[i]);
    219   delete[](FragmentList);
    220 
    221   LOG(0, FragmentCounter << " subgraph fragments have been removed.");
    222 
    223   // ===== 8b. gather keyset lists (graphs) from all subgraphs and transform into MoleculeListClass =====
    224   //if (FragmentationToDo) {    // we should always store the fragments again as coordination might have changed slightly without changing bond structure
    225   // allocate memory for the pointer array and transmorph graphs into full molecular fragments
    226   BondFragments = new MoleculeListClass(World::getPointer());
    227   int k=0;
    228   for(Graph::iterator runner = TotalGraph.begin(); runner != TotalGraph.end(); runner++) {
    229     KeySet test = (*runner).first;
    230     LOG(0, "Fragment No." << (*runner).second.first << " with TEFactor " << (*runner).second.second << ".");
    231     BondFragments->insert(StoreFragmentFromKeySet(test, World::getInstance().getConfig()));
    232     k++;
    233   }
    234   LOG(0, k << "/" << BondFragments->ListOfMolecules.size() << " fragments generated from the keysets.");
    235 
    236   // ===== 9. Save fragments' configuration and keyset files et al to disk ===
    237   if (BondFragments->ListOfMolecules.size() != 0) {
    238     // create the SortIndex from BFS labels to order in the config file
    239     int *SortIndex = NULL;
    240     CreateMappingLabelsToConfigSequence(SortIndex);
    241 
    242     LOG(1, "Writing " << BondFragments->ListOfMolecules.size() << " possible bond fragmentation configs");
    243     bool write_status = true;
    244     for (std::vector<std::string>::const_iterator iter = typelist.begin();
    245         iter != typelist.end();
    246         ++iter) {
    247       LOG(2, "INFO: Writing bond fragments for type " << (*iter) << ".");
    248       write_status = write_status
    249       && BondFragments->OutputConfigForListOfFragments(
    250           prefix,
    251           SortIndex,
    252           FormatParserStorage::getInstance().getTypeFromName(*iter));
    253     }
    254     if (write_status)
    255       LOG(1, "All configs written.");
    256     else
    257       LOG(1, "Some config writing failed.");
    258 
    259     // store force index reference file
    260     BondFragments->StoreForcesFile(prefix, SortIndex);
    261 
    262     // store keysets file
    263     TotalGraph.StoreKeySetFile(prefix);
    264 
    265     {
    266       // store Adjacency file
    267       std::string filename = prefix + ADJACENCYFILE;
    268       mol->StoreAdjacencyToFile(filename);
    269     }
    270 
    271     // store Hydrogen saturation correction file
    272     BondFragments->AddHydrogenCorrection(prefix);
    273 
    274     // store adaptive orders into file
    275     StoreOrderAtSiteFile(prefix);
    276 
    277     // restore orbital and Stop values
    278     //CalculateOrbitals(*configuration);
    279 
    280     // free memory for bond part
    281     LOG(1, "Freeing bond memory");
    282     delete[](SortIndex);
    283   } else {
    284     LOG(1, "FragmentList is zero on return, splitting failed.");
    285   }
    286   // remove all create molecules again from the World including their atoms
    287   for (MoleculeList::iterator iter = BondFragments->ListOfMolecules.begin();
    288       !BondFragments->ListOfMolecules.empty();
    289       iter = BondFragments->ListOfMolecules.begin()) {
    290     // remove copied atoms and molecule again
    291     molecule *mol = *iter;
    292     mol->removeAtomsinMolecule();
    293     World::getInstance().destroyMolecule(mol);
    294     BondFragments->ListOfMolecules.erase(iter);
    295   }
    296   delete(BondFragments);
     169  TranslateIndicesToGlobalIDs(FragmentList, TotalNumberOfKeySets, TotalGraph);
     170
     171  LOG(1, "STATUS: We have created " << TotalGraph.size() << " fragments.");
     172
     173
     174  // store adaptive orders into file
     175  StoreOrderAtSiteFile(prefix);
     176
    297177  LOG(0, "End of bond fragmentation.");
    298 
    299178  return ((int)(!FragmentationToDo)+1);    // 1 - continue, 2 - stop (no fragmentation occured)
    300179};
     
    317196 * \return pointer to Graph list
    318197 */
    319 void Fragmentation::FragmentBOSSANOVA(molecule *mol, Graph *&FragmentList, KeyStack &RootStack)
    320 {
     198void Fragmentation::FragmentBOSSANOVA(molecule *mol, Graph &FragmentList, KeyStack &RootStack)
     199{
     200  Info FunctionInfo(__func__);
    321201  Graph ***FragmentLowerOrdersList = NULL;
    322202  int NumLevels = 0;
     
    330210  int RootNr = 0;
    331211  UniqueFragments FragmentSearch;
    332 
    333   LOG(0, "Begin of FragmentBOSSANOVA.");
    334212
    335213  // FragmentLowerOrdersList is a 2D-array of pointer to MoleculeListClass objects, one dimension represents the ANOVA expansion of a single order (i.e. 5)
     
    420298  FreeAllOrdersList(FragmentLowerOrdersList, RootStack, mol);
    421299  delete[](NumMoleculesOfOrder);
    422 
    423   LOG(0, "End of FragmentBOSSANOVA.");
    424300};
    425 
    426 /** Stores a fragment from \a KeySet into \a molecule.
    427  * First creates the minimal set of atoms from the KeySet, then creates the bond structure from the complete
    428  * molecule and adds missing hydrogen where bonds were cut.
    429  * \param *out output stream for debugging messages
    430  * \param &Leaflet pointer to KeySet structure
    431  * \param IsAngstroem whether we have Ansgtroem or bohrradius
    432  * \return pointer to constructed molecule
    433  */
    434 molecule * Fragmentation::StoreFragmentFromKeySet(KeySet &Leaflet, bool IsAngstroem)
    435 {
    436   Info info(__func__);
    437   atom **SonList = new atom*[mol->getAtomCount()+1];
    438   molecule *Leaf = World::getInstance().createMolecule();
    439 
    440   for(int i=0;i<=mol->getAtomCount();i++)
    441     SonList[i] = NULL;
    442 
    443   StoreFragmentFromKeySet_Init(mol, Leaf, Leaflet, SonList);
    444   // create the bonds between all: Make it an induced subgraph and add hydrogen
    445 //  LOG(2, "Creating bonds from father graph (i.e. induced subgraph creation).");
    446   CreateInducedSubgraphOfFragment(mol, Leaf, SonList, IsAngstroem);
    447 
    448   //Leaflet->Leaf->ScanForPeriodicCorrection(out);
    449   delete[](SonList);
    450   return Leaf;
    451 };
    452 
    453301
    454302/** Estimates by educated guessing (using upper limit) the expected number of fragments.
     
    471319    c = (ListOfBonds.size() > c) ? ListOfBonds.size() : c;
    472320  }
    473   FragmentCount = mol->getNoNonHydrogen()*(1 << (c*order));
     321  FragmentCount = (saturation == DoSaturate ? mol->getNoNonHydrogen() : mol->getAtomCount()) *(1 << (c*order));
    474322  LOG(1, "Upper limit for this subgraph is " << FragmentCount << " for "
    475323      << mol->getNoNonHydrogen() << " non-H atoms with maximum bond degree of " << c << ".");
     
    479327
    480328/** Checks whether the OrderAtSite is still below \a Order at some site.
    481  * \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
     329 * \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
    482330 * \param *GlobalKeySetList list of keysets with global ids (valid in "this" molecule) needed for adaptive increase
    483331 * \param Order desired Order if positive, desired exponent in threshold criteria if negative (0 is single-step)
    484332 * \param path path to ENERGYPERFRAGMENT file (may be NULL if Order is non-negative)
     333 * \param LoopDoneAlready indicate whether we have done a fragmentation loop already
    485334 * \return true - needs further fragmentation, false - does not need fragmentation
    486335 */
    487 bool Fragmentation::CheckOrderAtSite(bool *AtomMask, Graph *GlobalKeySetList, int Order, std::string path)
     336bool Fragmentation::CheckOrderAtSite(AtomMask_t &AtomMask, const Graph &GlobalKeySetList, int Order, std::string path, bool LoopDoneAlready)
    488337{
    489338  bool status = false;
    490339
    491   // initialize mask list
    492   for(int i=mol->getAtomCount();i--;)
    493     AtomMask[i] = false;
    494 
    495340  if (Order < 0) { // adaptive increase of BondOrder per site
    496     if (AtomMask[mol->getAtomCount()] == true)  // break after one step
     341    if (LoopDoneAlready)  // break after one step
    497342      return false;
    498343
    499344    // transmorph graph keyset list into indexed KeySetList
    500     if (GlobalKeySetList == NULL) {
    501       ELOG(1, "Given global key set list (graph) is NULL!");
    502       return false;
    503     }
    504     AdaptivityMap * IndexKeySetList = GlobalKeySetList->GraphToAdaptivityMap();
     345    AdaptivityMap * IndexKeySetList = GlobalKeySetList.GraphToAdaptivityMap();
    505346
    506347    // parse the EnergyPerFragment file
     
    512353    if (IndexKeySetList->IsAdaptiveCriteriaListEmpty()) {
    513354      ELOG(2, "Unable to parse file, incrementing all.");
    514       for (molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
    515         if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
    516         {
    517           AtomMask[(*iter)->getNr()] = true;  // include all (non-hydrogen) atoms
    518           status = true;
    519         }
    520       }
     355      status = true;
    521356    } else {
    522       IndexKeySetList->MarkUpdateCandidates(AtomMask, Order, mol);
     357      // mark as false all sites that are below threshold already
     358      status = IndexKeySetList->MarkUpdateCandidates(AtomMask, Order, mol);
    523359    }
    524360
     
    526362  } else { // global increase of Bond Order
    527363    for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
    528       if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
    529       {
    530         AtomMask[(*iter)->getNr()] = true;  // include all (non-hydrogen) atoms
    531         if ((Order != 0) && ((*iter)->AdaptiveOrder < Order)) // && ((*iter)->AdaptiveOrder < MinimumRingSize[(*iter)->getNr()]))
     364      if (AtomMask.isTrue((*iter)->getNr())) { // skip masked out
     365        // remove all that have reached desired order
     366        if ((Order != 0) && ((*iter)->AdaptiveOrder >= Order)) // && ((*iter)->AdaptiveOrder < MinimumRingSize[(*iter)->getNr()]))
     367          AtomMask.setFalse((*iter)->getNr());
     368        else
    532369          status = true;
    533370      }
    534371    }
    535     if ((!Order) && (!AtomMask[mol->getAtomCount()]))  // single stepping, just check
     372    if ((!Order) && (!LoopDoneAlready))  // single stepping, just check
    536373      status = true;
    537374
     
    576413/** Parses pairs(Atom::Nr, Atom::AdaptiveOrder) from file and stores in molecule's Atom's.
    577414 * Atoms not present in the file get "0".
     415 * \param atomids atoms to fragment, used in AtomMask
    578416 * \param &path path to file ORDERATSITEFILEe
    579417 * \return true - file found and scanned, false - file not found
    580418 * \sa ParseKeySetFile() and CheckAdjacencyFileAgainstMolecule() as this is meant to be used in conjunction with the two
    581419 */
    582 bool Fragmentation::ParseOrderAtSiteFromFile(std::string &path)
    583 {
    584   unsigned char *OrderArray = new unsigned char[mol->getAtomCount()];
    585   bool *MaxArray = new bool[mol->getAtomCount()];
     420bool Fragmentation::ParseOrderAtSiteFromFile(const std::vector<atomId_t> &atomids, std::string &path)
     421{
     422  Info FunctionInfo(__func__);
     423  typedef unsigned char order_t;
     424  typedef std::map<atomId_t, order_t> OrderArray_t;
     425  OrderArray_t OrderArray;
     426  AtomMask_t MaxArray(atomids);
    586427  bool status;
    587428  int AtomNr, value;
     
    589430  ifstream file;
    590431
    591   for(int i=0;i<mol->getAtomCount();i++) {
    592     OrderArray[i] = 0;
    593     MaxArray[i] = false;
    594   }
    595 
    596   LOG(1, "Begin of ParseOrderAtSiteFromFile");
    597432  line = path + ORDERATSITEFILE;
    598433  file.open(line.c_str());
     
    605440        OrderArray[AtomNr] = value;
    606441        file >> value;
    607         MaxArray[AtomNr] = value;
     442        MaxArray.setValue(AtomNr, (bool)value);
    608443        //LOG(2, "AtomNr " << AtomNr << " with order " << (int)OrderArray[AtomNr] << " and max order set to " << (int)MaxArray[AtomNr] << ".");
    609444      }
     
    614449    for(molecule::iterator iter=mol->begin();iter!=mol->end();++iter){
    615450      (*iter)->AdaptiveOrder = OrderArray[(*iter)->getNr()];
    616       (*iter)->MaxOrder = MaxArray[(*iter)->getNr()];
     451      (*iter)->MaxOrder = MaxArray.isTrue((*iter)->getNr());
    617452    }
    618453    //SetAtomValueToIndexedArray( OrderArray, &atom::getNr(), &atom::AdaptiveOrder );
     
    625460    status = false;
    626461  }
    627   delete[](OrderArray);
    628   delete[](MaxArray);
    629 
    630   LOG(1, "End of ParseOrderAtSiteFromFile");
     462
    631463  return status;
    632464};
    633465
    634 /** Create a SortIndex to map from atomic labels to the sequence in which the atoms are given in the config file.
    635  * \param *out output stream for debugging
    636  * \param *&SortIndex Mapping array of size molecule::AtomCount
    637  * \return true - success, false - failure of SortIndex alloc
    638  */
    639 bool Fragmentation::CreateMappingLabelsToConfigSequence(int *&SortIndex)
    640 {
    641   if (SortIndex != NULL) {
    642     LOG(1, "SortIndex is " << SortIndex << " and not NULL as expected.");
     466/** Fills the root stack for sites to be used as root in fragmentation depending on order or adaptivity criteria
     467 * Again, as in \sa FillBondStructureFromReference steps recursively through each Leaf in this chain list of molecule's.
     468 * \param &RootStack stack to be filled
     469 * \param AtomMask defines true/false per global Atom::Nr to mask in/out each nuclear site
     470 * \return true - stack is non-empty, fragmentation necessary, false - stack is empty, no more sites to update
     471 */
     472void Fragmentation::FillRootStackForSubgraphs(KeyStack &RootStack, const AtomMask_t &AtomMask)
     473{
     474  for(molecule::const_iterator iter = mol->begin(); iter != mol->end(); ++iter) {
     475    const atom * const Father = (*iter)->GetTrueFather();
     476    if (AtomMask.isTrue(Father->getNr())) // apply mask
     477      if ((saturation == DontSaturate) || ((*iter)->getType()->getAtomicNumber() != 1)) // skip hydrogen
     478        RootStack.push_front((*iter)->getNr());
     479  }
     480}
     481
     482/** The indices per keyset are compared to the respective father's Atom::Nr in each subgraph and thus put into \a **&FragmentList.
     483 * \param *KeySetList list with all keysets
     484 * \param ListOfLocalAtoms Lookup table for each subgraph and index of each atom in global molecule, may be NULL on start, then it is filled
     485 * \param **&FragmentList list to be allocated and returned
     486 * \param FreeList true - ***ListOfLocalAtoms is free'd before return, false - it is not
     487 * \retuen true - success, false - failure
     488 */
     489bool Fragmentation::AssignKeySetsToFragment(Graph &KeySetList, ListOfLocalAtoms_t &ListOfLocalAtoms, Graph &FragmentList, bool FreeList)
     490{
     491  Info FunctionInfo(__func__);
     492  bool status = true;
     493  size_t KeySetCounter = 0;
     494
     495  // fill ListOfLocalAtoms if NULL was given
     496  if (!mol->FillListOfLocalAtoms(ListOfLocalAtoms, mol->getAtomCount())) {
     497    LOG(1, "Filling of ListOfLocalAtoms failed.");
    643498    return false;
    644499  }
    645   SortIndex = new int[mol->getAtomCount()+1];
    646   for(int i=mol->getAtomCount()+1;i--;)
    647     SortIndex[i] = -1;
    648 
    649   int AtomNo = 0;
    650   for(molecule::const_iterator iter=mol->begin();iter!=mol->end();++iter){
    651     ASSERT(SortIndex[(*iter)->getNr()]==-1,"Same SortIndex set twice");
    652     SortIndex[(*iter)->getNr()] = AtomNo++;
    653   }
    654 
    655   return true;
    656 };
    657 
    658 
    659 /** Initializes some value for putting fragment of \a *mol into \a *Leaf.
    660  * \param *mol total molecule
    661  * \param *Leaf fragment molecule
    662  * \param &Leaflet pointer to KeySet structure
    663  * \param **SonList calloc'd list which atom of \a *Leaf is a son of which atom in \a *mol
    664  * \return number of atoms in fragment
    665  */
    666 int Fragmentation::StoreFragmentFromKeySet_Init(molecule *mol, molecule *Leaf, KeySet &Leaflet, atom **SonList)
    667 {
    668   atom *FatherOfRunner = NULL;
    669 
    670   // first create the minimal set of atoms from the KeySet
    671   int size = 0;
    672   for(KeySet::iterator runner = Leaflet.begin(); runner != Leaflet.end(); runner++) {
    673     FatherOfRunner = mol->FindAtom((*runner));  // find the id
    674     SonList[FatherOfRunner->getNr()] = Leaf->AddCopyAtom(FatherOfRunner);
    675     size++;
    676   }
    677   return size;
    678 };
    679 
    680 
    681 /** Creates an induced subgraph out of a fragmental key set, adding bonds and hydrogens (if treated specially).
    682  * \param *out output stream for debugging messages
    683  * \param *mol total molecule
    684  * \param *Leaf fragment molecule
    685  * \param IsAngstroem whether we have Ansgtroem or bohrradius
    686  * \param **SonList list which atom of \a *Leaf is a son of which atom in \a *mol
    687  */
    688 void Fragmentation::CreateInducedSubgraphOfFragment(molecule *mol, molecule *Leaf, atom **SonList, bool IsAngstroem)
    689 {
    690   bool LonelyFlag = false;
    691   atom *OtherFather = NULL;
    692   atom *FatherOfRunner = NULL;
    693 
    694   // we increment the iter just before skipping the hydrogen
    695   // as we use AddBond, we cannot have a const_iterator here
    696   for (molecule::iterator iter = Leaf->begin(); iter != Leaf->end();) {
    697     LonelyFlag = true;
    698     FatherOfRunner = (*iter)->father;
    699     ASSERT(FatherOfRunner,"Atom without father found");
    700     if (SonList[FatherOfRunner->getNr()] != NULL)  {  // check if this, our father, is present in list
    701       // create all bonds
    702       const BondList& ListOfBonds = FatherOfRunner->getListOfBonds();
    703       for (BondList::const_iterator BondRunner = ListOfBonds.begin();
    704           BondRunner != ListOfBonds.end();
    705           ++BondRunner) {
    706         OtherFather = (*BondRunner)->GetOtherAtom(FatherOfRunner);
    707         if (SonList[OtherFather->getNr()] != NULL) {
    708 //          LOG(2, "INFO: Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->getNr()]
    709 //              << " is bound to " << *OtherFather << ", whose son is "
    710 //              << *SonList[OtherFather->getNr()] << ".");
    711           if (OtherFather->getNr() > FatherOfRunner->getNr()) { // add bond (Nr check is for adding only one of both variants: ab, ba)
    712             std::stringstream output;
    713 //            output << "ACCEPT: Adding Bond: "
    714             output << Leaf->AddBond((*iter), SonList[OtherFather->getNr()], (*BondRunner)->BondDegree);
    715 //            LOG(3, output.str());
    716             //NumBonds[(*iter)->getNr()]++;
    717           } else {
    718 //            LOG(3, "REJECY: Not adding bond, labels in wrong order.");
    719           }
    720           LonelyFlag = false;
    721         } else {
    722 //          LOG(2, "INFO: Father " << *FatherOfRunner << " of son " << *SonList[FatherOfRunner->getNr()]
    723 //              << " is bound to " << *OtherFather << ", who has no son in this fragment molecule.");
    724           if (saturation == DoSaturate) {
    725 //          LOG(3, "ACCEPT: Adding Hydrogen to " << (*iter)->Name << " and a bond in between.");
    726             if (!Leaf->AddHydrogenReplacementAtom((*BondRunner), (*iter), FatherOfRunner, OtherFather, IsAngstroem))
    727               exit(1);
    728           }
    729           //NumBonds[(*iter)->getNr()] += Binder->BondDegree;
    730         }
     500
     501  if (KeySetList.size() != 0) { // if there are some scanned keysets at all
     502    // assign scanned keysets
     503    KeySet TempSet;
     504    for (Graph::iterator runner = KeySetList.begin(); runner != KeySetList.end(); runner++) { // key sets contain global numbers!
     505      if (ListOfLocalAtoms[mol->FindAtom(*((*runner).first.begin()))->getNr()] != NULL) {// as we may assume that that bond structure is unchanged, we only test the first key in each set
     506        // translate keyset to local numbers
     507        for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
     508          TempSet.insert(ListOfLocalAtoms[mol->FindAtom(*sprinter)->getNr()]->getNr());
     509        // insert into FragmentList
     510        FragmentList.insert(GraphPair(TempSet, pair<int, double> (KeySetCounter++, (*runner).second.second)));
    731511      }
    732     } else {
    733     ELOG(1, "Son " << (*iter)->getName() << " has father " << FatherOfRunner->getName() << " but its entry in SonList is " << SonList[FatherOfRunner->getNr()] << "!");
    734     }
    735     if ((LonelyFlag) && (Leaf->getAtomCount() > 1)) {
    736       LOG(0, **iter << "has got bonds only to hydrogens!");
    737     }
    738     ++iter;
    739     if (saturation == DoSaturate) {
    740       while ((iter != Leaf->end()) && ((*iter)->getType()->getAtomicNumber() == 1)){ // skip added hydrogen
    741         iter++;
    742       }
    743     }
    744   }
    745 };
    746 
    747 /** Sets the desired output types of the fragment configurations.
    748  *
    749  * @param types vector of desired types.
    750  */
    751 void Fragmentation::setOutputTypes(const std::vector<std::string> &types)
    752 {
    753   typelist = types;
     512      TempSet.clear();
     513    }
     514  } else
     515    LOG(1, "KeySetList is NULL or empty.");
     516
     517  if (FreeList) {
     518    // free the index lookup list
     519    ListOfLocalAtoms.clear();
     520  }
     521  return status;
    754522}
     523
     524/** Translate list into global numbers (i.e. ones that are valid in "this" molecule, not in MolecularWalker->Leaf)
     525 * \param &FragmentList Graph with local numbers per fragment
     526 * \param &TotalNumberOfKeySets global key set counter
     527 * \param &TotalGraph Graph to be filled with global numbers
     528 */
     529void Fragmentation::TranslateIndicesToGlobalIDs(Graph &FragmentList, int &TotalNumberOfKeySets, Graph &TotalGraph)
     530{
     531  Info FunctionInfo(__func__);
     532  for (Graph::iterator runner = FragmentList.begin(); runner != FragmentList.end(); runner++) {
     533    KeySet TempSet;
     534    for (KeySet::iterator sprinter = (*runner).first.begin(); sprinter != (*runner).first.end(); sprinter++)
     535      TempSet.insert((mol->FindAtom(*sprinter))->GetTrueFather()->getId());
     536    TotalGraph.insert(GraphPair(TempSet, pair<int, double> (TotalNumberOfKeySets++, (*runner).second.second)));
     537  }
     538}
     539
Note: See TracChangeset for help on using the changeset viewer.